chore(server): allow non-nullable NQ -> NQ object relationships

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9353
GitOrigin-RevId: 9da95675d224f3045509592c2515b7afa2500d00
This commit is contained in:
Daniel Harvey 2023-05-31 11:32:57 +01:00 committed by hasura-bot
parent b19eff22e9
commit 7d011644ac
12 changed files with 75 additions and 44 deletions

View File

@ -204,6 +204,7 @@ fromRemoteRelationFieldsG existingJoins joinColumns (IR.FieldName name, field) =
IR.AnnRelationSelectG IR.AnnRelationSelectG
(IR.RelName $ mkNonEmptyTextUnsafe name) (IR.RelName $ mkNonEmptyTextUnsafe name)
joinColumns joinColumns
IR.Nullable
annotatedRelationship annotatedRelationship
-- | Top/root-level 'Select'. All descendent/sub-translations are collected to produce a root TSQL.Select. -- | Top/root-level 'Select'. All descendent/sub-translations are collected to produce a root TSQL.Select.

View File

@ -31,6 +31,7 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
import Hasura.Backends.Postgres.Translate.Types import Hasura.Backends.Postgres.Translate.Types
import Hasura.Prelude import Hasura.Prelude
import Hasura.RQL.IR.Select (ConnectionSlice (SliceFirst, SliceLast)) import Hasura.RQL.IR.Select (ConnectionSlice (SliceFirst, SliceLast))
import Hasura.RQL.Types.Relationships.Local (Nullable (..))
generateSQLSelect :: generateSQLSelect ::
-- | Pre join condition for lateral joins -- | Pre join condition for lateral joins
@ -86,9 +87,9 @@ generateSQLSelect joinCondition selectSource selectNode =
S.WhereFrag $ S.simplifyBoolExp $ S.BEBin S.AndOp joinCond whereCond S.WhereFrag $ S.simplifyBoolExp $ S.BEBin S.AndOp joinCond whereCond
-- function to create a joined from item from two from items -- function to create a joined from item from two from items
leftOuterJoin current new = leftOuterJoin current (new, joinType) =
S.FIJoin S.FIJoin
$ S.JoinExpr current S.LeftOuter new $ S.JoinExpr current joinType new
$ S.JoinOn $ S.JoinOn
$ S.BELit True $ S.BELit True
@ -102,33 +103,40 @@ generateSQLSelect joinCondition selectSource selectNode =
<> map computedFieldToFromItem (HashMap.toList computedFields) <> map computedFieldToFromItem (HashMap.toList computedFields)
objectRelationToFromItem :: objectRelationToFromItem ::
(ObjectRelationSource, SelectNode) -> S.FromItem (ObjectRelationSource, SelectNode) -> (S.FromItem, S.JoinType)
objectRelationToFromItem (objectRelationSource, node) = objectRelationToFromItem (objectRelationSource, node) =
let ObjectRelationSource _ colMapping objectSelectSource = objectRelationSource let ObjectRelationSource
{ _orsRelationMapping = colMapping,
_orsSelectSource = objectSelectSource,
_orsNullable = nullable
} = objectRelationSource
alias = S.toTableAlias $ _ossPrefix objectSelectSource alias = S.toTableAlias $ _ossPrefix objectSelectSource
source = objectSelectSourceToSelectSource objectSelectSource source = objectSelectSourceToSelectSource objectSelectSource
select = generateSQLSelect (mkJoinCond baseSelectIdentifier colMapping) source node select = generateSQLSelect (mkJoinCond baseSelectIdentifier colMapping) source node
in S.mkLateralFromItem select alias joinType = case nullable of
Nullable -> S.LeftOuter
NotNullable -> S.Inner
in (S.mkLateralFromItem select alias, joinType)
arrayRelationToFromItem :: arrayRelationToFromItem ::
(ArrayRelationSource, MultiRowSelectNode) -> S.FromItem (ArrayRelationSource, MultiRowSelectNode) -> (S.FromItem, S.JoinType)
arrayRelationToFromItem (arrayRelationSource, arraySelectNode) = arrayRelationToFromItem (arrayRelationSource, arraySelectNode) =
let ArrayRelationSource _ colMapping source = arrayRelationSource let ArrayRelationSource _ colMapping source = arrayRelationSource
alias = S.toTableAlias $ _ssPrefix source alias = S.toTableAlias $ _ssPrefix source
select = select =
generateSQLSelectFromArrayNode source arraySelectNode generateSQLSelectFromArrayNode source arraySelectNode
$ mkJoinCond baseSelectIdentifier colMapping $ mkJoinCond baseSelectIdentifier colMapping
in S.mkLateralFromItem select alias in (S.mkLateralFromItem select alias, S.LeftOuter)
arrayConnectionToFromItem :: arrayConnectionToFromItem ::
(ArrayConnectionSource, MultiRowSelectNode) -> S.FromItem (ArrayConnectionSource, MultiRowSelectNode) -> (S.FromItem, S.JoinType)
arrayConnectionToFromItem (arrayConnectionSource, arraySelectNode) = arrayConnectionToFromItem (arrayConnectionSource, arraySelectNode) =
let selectWith = connectionToSelectWith baseSelectAlias arrayConnectionSource arraySelectNode let selectWith = connectionToSelectWith baseSelectAlias arrayConnectionSource arraySelectNode
alias = S.toTableAlias $ _ssPrefix $ _acsSource arrayConnectionSource alias = S.toTableAlias $ _ssPrefix $ _acsSource arrayConnectionSource
in S.FISelectWith (S.Lateral True) selectWith alias in (S.FISelectWith (S.Lateral True) selectWith alias, S.LeftOuter)
computedFieldToFromItem :: computedFieldToFromItem ::
(ComputedFieldTableSetSource, MultiRowSelectNode) -> S.FromItem (ComputedFieldTableSetSource, MultiRowSelectNode) -> (S.FromItem, S.JoinType)
computedFieldToFromItem (computedFieldTableSource, node) = computedFieldToFromItem (computedFieldTableSource, node) =
let ComputedFieldTableSetSource _ source = computedFieldTableSource let ComputedFieldTableSetSource _ source = computedFieldTableSource
internalSelect = generateSQLSelect (S.BELit True) source $ _mrsnSelectNode node internalSelect = generateSQLSelect (S.BELit True) source $ _mrsnSelectNode node
@ -138,7 +146,7 @@ generateSQLSelect joinCondition selectSource selectNode =
{ S.selExtr = _mrsnTopExtractors node, { S.selExtr = _mrsnTopExtractors node,
S.selFrom = Just $ S.FromExp [S.mkSelFromItem internalSelect alias] S.selFrom = Just $ S.FromExp [S.mkSelFromItem internalSelect alias]
} }
in S.mkLateralFromItem select alias in (S.mkLateralFromItem select alias, S.LeftOuter)
-- | Create a select query -- | Create a select query
generateSQLSelectFromArrayNode :: generateSQLSelectFromArrayNode ::

View File

@ -130,7 +130,7 @@ processOrderByItems sourcePrefix' fieldAlias' similarArrayFields distOnCols = \c
(tableIdentifierToIdentifier relSourcePrefix) (tableIdentifierToIdentifier relSourcePrefix)
(S.FISimple relTable Nothing) (S.FISimple relTable Nothing)
(toSQLBoolExp (S.QualTable relTable) relFilter) (toSQLBoolExp (S.QualTable relTable) relFilter)
relSource = ObjectRelationSource relName colMapping selectSource relSource = ObjectRelationSource relName colMapping selectSource Nullable
pure pure
( relSource, ( relSource,
HashMap.singleton relOrderByAlias relOrdByExp, HashMap.singleton relOrderByAlias relOrdByExp,

View File

@ -291,7 +291,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
AFNodeId _ sn tn pKeys -> pure $ mkNodeId sn tn pKeys AFNodeId _ sn tn pKeys -> pure $ mkNodeId sn tn pKeys
AFColumn c -> toSQLCol c AFColumn c -> toSQLCol c
AFObjectRelation objSel -> withWriteObjectRelation $ do AFObjectRelation objSel -> withWriteObjectRelation $ do
let AnnRelationSelectG relName relMapping annObjSel = objSel let AnnRelationSelectG relName relMapping nullable annObjSel = objSel
AnnObjectSelectG objAnnFields target targetFilter = annObjSel AnnObjectSelectG objAnnFields target targetFilter = annObjSel
objRelSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName objRelSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName
sourcePrefixes = mkSourcePrefixes objRelSourcePrefix sourcePrefixes = mkSourcePrefixes objRelSourcePrefix
@ -314,7 +314,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
(_pfThis sourcePrefixes) (_pfThis sourcePrefixes)
(S.FIIdentifier nativeQueryIdentifier) (S.FIIdentifier nativeQueryIdentifier)
(toSQLBoolExp (S.QualifiedIdentifier nativeQueryIdentifier Nothing) targetFilter) (toSQLBoolExp (S.QualifiedIdentifier nativeQueryIdentifier Nothing) targetFilter)
objRelSource = ObjectRelationSource relName relMapping selectSource objRelSource = ObjectRelationSource relName relMapping selectSource nullable
pure pure
( objRelSource, ( objRelSource,
HashMap.fromList [annFieldsExtr], HashMap.fromList [annFieldsExtr],
@ -326,7 +326,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
(_pfThis sourcePrefixes) (_pfThis sourcePrefixes)
(S.FISimple tableFrom Nothing) (S.FISimple tableFrom Nothing)
(toSQLBoolExp (S.QualTable tableFrom) targetFilter) (toSQLBoolExp (S.QualTable tableFrom) targetFilter)
objRelSource = ObjectRelationSource relName relMapping selectSource objRelSource = ObjectRelationSource relName relMapping selectSource Nullable
pure pure
( objRelSource, ( objRelSource,
HashMap.fromList [annFieldsExtr], HashMap.fromList [annFieldsExtr],
@ -496,7 +496,7 @@ processArrayRelation ::
processArrayRelation sourcePrefixes fieldAlias relAlias arrSel _tCase = processArrayRelation sourcePrefixes fieldAlias relAlias arrSel _tCase =
case arrSel of case arrSel of
ASSimple annArrRel -> withWriteArrayRelation $ do ASSimple annArrRel -> withWriteArrayRelation $ do
let AnnRelationSelectG _ colMapping sel = annArrRel let AnnRelationSelectG _ colMapping _ sel = annArrRel
permLimitSubQuery = permLimitSubQuery =
maybe PLSQNotRequired PLSQRequired $ _tpLimit $ _asnPerm sel maybe PLSQNotRequired PLSQRequired $ _tpLimit $ _asnPerm sel
(source, nodeExtractors) <- (source, nodeExtractors) <-
@ -514,7 +514,7 @@ processArrayRelation sourcePrefixes fieldAlias relAlias arrSel _tCase =
() ()
) )
ASAggregate aggSel -> withWriteArrayRelation $ do ASAggregate aggSel -> withWriteArrayRelation $ do
let AnnRelationSelectG _ colMapping sel = aggSel let AnnRelationSelectG _ colMapping _ sel = aggSel
(source, nodeExtractors, topExtr) <- (source, nodeExtractors, topExtr) <-
processAnnAggregateSelect sourcePrefixes fieldAlias sel processAnnAggregateSelect sourcePrefixes fieldAlias sel
pure pure
@ -524,7 +524,7 @@ processArrayRelation sourcePrefixes fieldAlias relAlias arrSel _tCase =
() ()
) )
ASConnection connSel -> withWriteArrayConnection $ do ASConnection connSel -> withWriteArrayConnection $ do
let AnnRelationSelectG _ colMapping sel = connSel let AnnRelationSelectG _ colMapping _ sel = connSel
(source, topExtractor, nodeExtractors) <- (source, topExtractor, nodeExtractors) <-
processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping sel processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping sel
pure pure

View File

@ -12,7 +12,7 @@ module Hasura.Backends.Postgres.Translate.Types
DistinctAndOrderByExpr (ASorting), DistinctAndOrderByExpr (ASorting),
JoinTree (..), JoinTree (..),
MultiRowSelectNode (..), MultiRowSelectNode (..),
ObjectRelationSource (ObjectRelationSource), ObjectRelationSource (..),
ObjectSelectSource (ObjectSelectSource, _ossPrefix), ObjectSelectSource (ObjectSelectSource, _ossPrefix),
PermissionLimitSubQuery (..), PermissionLimitSubQuery (..),
SelectNode (SelectNode), SelectNode (SelectNode),
@ -38,6 +38,7 @@ import Hasura.NativeQuery.Metadata (InterpolatedQuery)
import Hasura.Prelude import Hasura.Prelude
import Hasura.RQL.IR.Select import Hasura.RQL.IR.Select
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Relationships.Local (Nullable)
data SourcePrefixes = SourcePrefixes data SourcePrefixes = SourcePrefixes
{ -- | Current source prefix { -- | Current source prefix
@ -169,7 +170,8 @@ objectSelectSourceToSelectSource ObjectSelectSource {..} =
data ObjectRelationSource = ObjectRelationSource data ObjectRelationSource = ObjectRelationSource
{ _orsRelationshipName :: RelName, { _orsRelationshipName :: RelName,
_orsRelationMapping :: HashMap.HashMap Postgres.PGCol Postgres.PGCol, _orsRelationMapping :: HashMap.HashMap Postgres.PGCol Postgres.PGCol,
_orsSelectSource :: ObjectSelectSource _orsSelectSource :: ObjectSelectSource,
_orsNullable :: Nullable
} }
deriving (Generic, Show) deriving (Generic, Show)

View File

@ -33,6 +33,7 @@ import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column (ColumnType, fromCol) import Hasura.RQL.Types.Column (ColumnType, fromCol)
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Relationships.Local (Nullable (..))
import Hasura.RQL.Types.ResultCustomization import Hasura.RQL.Types.ResultCustomization
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.RemoteSchema.SchemaCache import Hasura.RemoteSchema.SchemaCache
@ -197,11 +198,11 @@ convertRemoteSourceRelationship
relationshipField = case relationship of relationshipField = case relationship of
SourceRelationshipObject s -> SourceRelationshipObject s ->
AFObjectRelation $ AnnRelationSelectG relName columnMapping s AFObjectRelation $ AnnRelationSelectG relName columnMapping Nullable s
SourceRelationshipArray s -> SourceRelationshipArray s ->
AFArrayRelation $ ASSimple $ AnnRelationSelectG relName columnMapping s AFArrayRelation $ ASSimple $ AnnRelationSelectG relName columnMapping Nullable s
SourceRelationshipArrayAggregate s -> SourceRelationshipArrayAggregate s ->
AFArrayRelation $ ASAggregate $ AnnRelationSelectG relName columnMapping s AFArrayRelation $ ASAggregate $ AnnRelationSelectG relName columnMapping Nullable s
argumentIdField = argumentIdField =
( fromCol @b argumentIdColumn, ( fromCol @b argumentIdColumn,

View File

@ -1448,7 +1448,7 @@ relationshipField table ri = runMaybeT do
$ P.subselection_ relFieldName desc selectionSetParser $ P.subselection_ relFieldName desc selectionSetParser
<&> \fields -> <&> \fields ->
IR.AFObjectRelation IR.AFObjectRelation
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) $ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable
$ IR.AnnObjectSelectG fields (IR.FromTable otherTableName) $ IR.AnnObjectSelectG fields (IR.FromTable otherTableName)
$ deduplicatePermissions $ deduplicatePermissions
$ IR._tpFilter $ IR._tpFilter
@ -1460,7 +1460,7 @@ relationshipField table ri = runMaybeT do
otherTableParser <&> \selectExp -> otherTableParser <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) $ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable
$ deduplicatePermissions' selectExp $ deduplicatePermissions' selectExp
relAggFieldName = applyFieldNameCaseCust tCase $ relFieldName <> Name.__aggregate relAggFieldName = applyFieldNameCaseCust tCase $ relFieldName <> Name.__aggregate
relAggDesc = Just $ G.Description "An aggregate relationship" relAggDesc = Just $ G.Description "An aggregate relationship"
@ -1479,8 +1479,8 @@ relationshipField table ri = runMaybeT do
pure pure
$ catMaybes $ catMaybes
[ Just arrayRelField, [ Just arrayRelField,
fmap (IR.AFArrayRelation . IR.ASAggregate . IR.AnnRelationSelectG (riName ri) (riMapping ri)) <$> remoteAggField, fmap (IR.AFArrayRelation . IR.ASAggregate . IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable) <$> remoteAggField,
fmap (IR.AFArrayRelation . IR.ASConnection . IR.AnnRelationSelectG (riName ri) (riMapping ri)) <$> remoteConnectionField fmap (IR.AFArrayRelation . IR.ASConnection . IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable) <$> remoteConnectionField
] ]
tablePermissionsInfo :: (Backend b) => SelPermInfo b -> TablePerms b tablePermissionsInfo :: (Backend b) => SelPermInfo b -> TablePerms b

View File

@ -200,11 +200,11 @@ parseLogicalModelField relationshipInfo column logimoField = do
( LogicalModelField ( LogicalModelField
{ lmfType = { lmfType =
LogicalModelTypeReference LogicalModelTypeReference
(LogicalModelTypeReferenceC {lmtrReference}) (LogicalModelTypeReferenceC {lmtrNullable, lmtrReference})
} }
) -> do ) -> do
-- we currently ignore nullability and assume the field is nullable
relName <- hoistMaybe $ columnToRelName @b column relName <- hoistMaybe $ columnToRelName @b column
-- lookup the reference in the data source -- lookup the reference in the data source
relationship <- relationship <-
InsOrdHashMap.lookup relName relationshipInfo InsOrdHashMap.lookup relName relationshipInfo
@ -215,14 +215,14 @@ parseLogicalModelField relationshipInfo column logimoField = do
<> commaSeparated (map relNameToTxt (InsOrdHashMap.keys relationshipInfo)) <> commaSeparated (map relNameToTxt (InsOrdHashMap.keys relationshipInfo))
<> "]." <> "]."
) )
logicalModelObjectRelationshipField @b @r @m @n lmtrReference relationship logicalModelObjectRelationshipField @b @r @m @n lmtrReference (nullableFromBool lmtrNullable) relationship
( LogicalModelField ( LogicalModelField
{ lmfType = { lmfType =
LogicalModelTypeArray LogicalModelTypeArray
( LogicalModelTypeArrayC ( LogicalModelTypeArrayC
{ lmtaArray = { lmtaArray =
LogicalModelTypeReference (LogicalModelTypeReferenceC {lmtrReference}), LogicalModelTypeReference (LogicalModelTypeReferenceC {lmtrReference, lmtrNullable = innerNullability}),
lmtaNullable lmtaNullable = arrayNullability
} }
) )
} }
@ -232,9 +232,12 @@ parseLogicalModelField relationshipInfo column logimoField = do
relName <- hoistMaybe $ columnToRelName @b column relName <- hoistMaybe $ columnToRelName @b column
-- lookup the reference in the data source -- lookup the reference in the data source
relationship <- hoistMaybe $ InsOrdHashMap.lookup relName relationshipInfo relationship <- hoistMaybe $ InsOrdHashMap.lookup relName relationshipInfo
let nullability = if lmtaNullable then Nullable else NotNullable
logicalModelArrayRelationshipField @b @r @m @n lmtrReference nullability relationship logicalModelArrayRelationshipField @b @r @m @n
lmtrReference
(nullableFromBool arrayNullability)
(nullableFromBool innerNullability)
relationship
( LogicalModelField ( LogicalModelField
{ lmfType = { lmfType =
LogicalModelTypeArray LogicalModelTypeArray
@ -250,6 +253,10 @@ parseLogicalModelField relationshipInfo column logimoField = do
) -> ) ->
throw500 "Nested arrays are not currently implemented" throw500 "Nested arrays are not currently implemented"
nullableFromBool :: Bool -> Nullable
nullableFromBool True = Nullable
nullableFromBool False = NotNullable
defaultLogicalModelSelectionSet :: defaultLogicalModelSelectionSet ::
forall b r m n. forall b r m n.
( MonadBuildSchema b r m n, ( MonadBuildSchema b r m n,
@ -421,9 +428,10 @@ logicalModelObjectRelationshipField ::
MonadBuildSchema b r m n MonadBuildSchema b r m n
) => ) =>
LogicalModelName -> LogicalModelName ->
Nullable ->
RelInfo b -> RelInfo b ->
MaybeT (SchemaT r m) (FieldParser n (AnnotatedField b)) MaybeT (SchemaT r m) (FieldParser n (AnnotatedField b))
logicalModelObjectRelationshipField logicalModelName ri | riType ri == ObjRel = logicalModelObjectRelationshipField logicalModelName nullability ri | riType ri == ObjRel =
case riTarget ri of case riTarget ri of
RelTargetNativeQuery nativeQueryName -> do RelTargetNativeQuery nativeQueryName -> do
nativeQueryInfo <- lift $ askNativeQueryInfo nativeQueryName nativeQueryInfo <- lift $ askNativeQueryInfo nativeQueryName
@ -443,16 +451,22 @@ logicalModelObjectRelationshipField logicalModelName ri | riType ri == ObjRel =
relFieldName <- lift $ textToName $ relNameToTxt $ riName ri relFieldName <- lift $ textToName $ relNameToTxt $ riName ri
let objectRelDesc = Just $ G.Description "An object relationship" let objectRelDesc = Just $ G.Description "An object relationship"
nativeQueryParser <- MaybeT $ selectNativeQueryObject nativeQueryInfo relFieldName objectRelDesc nativeQueryParser <- MaybeT $ selectNativeQueryObject nativeQueryInfo relFieldName objectRelDesc
-- this only affects the generated GraphQL type
let nullabilityModifier =
case nullability of
Nullable -> id
NotNullable -> IP.nonNullableField
pure pure
$ nullabilityModifier
$ nativeQueryParser $ nativeQueryParser
<&> \selectExp -> <&> \selectExp ->
IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (riMapping ri) selectExp) IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (riMapping ri) nullability selectExp)
RelTargetTable _otherTableName -> do RelTargetTable _otherTableName -> do
throw500 "Object relationships from logical models to tables are not implemented" throw500 "Object relationships from logical models to tables are not implemented"
logicalModelObjectRelationshipField _ _ = logicalModelObjectRelationshipField _ _ _ =
hoistMaybe Nothing -- the target logical model expected an object relationship, but this was an array hoistMaybe Nothing -- the target logical model expected an object relationship, but this was an array
-- | Field parsers for a logical model relationship -- | Field parsers for a logical model relationship
@ -463,9 +477,10 @@ logicalModelArrayRelationshipField ::
) => ) =>
LogicalModelName -> LogicalModelName ->
Nullable -> Nullable ->
Nullable ->
RelInfo b -> RelInfo b ->
MaybeT (SchemaT r m) (FieldParser n (AnnotatedField b)) MaybeT (SchemaT r m) (FieldParser n (AnnotatedField b))
logicalModelArrayRelationshipField logicalModelName nullability ri | riType ri == ArrRel = logicalModelArrayRelationshipField logicalModelName arrayNullability innerNullability ri | riType ri == ArrRel =
case riTarget ri of case riTarget ri of
RelTargetNativeQuery nativeQueryName -> do RelTargetNativeQuery nativeQueryName -> do
nativeQueryInfo <- lift $ askNativeQueryInfo nativeQueryName nativeQueryInfo <- lift $ askNativeQueryInfo nativeQueryName
@ -485,15 +500,15 @@ logicalModelArrayRelationshipField logicalModelName nullability ri | riType ri =
let objectRelDesc = Just $ G.Description "An array relationship" let objectRelDesc = Just $ G.Description "An array relationship"
nativeQueryParser <- MaybeT $ selectNativeQuery nativeQueryInfo relFieldName nullability objectRelDesc nativeQueryParser <- MaybeT $ selectNativeQuery nativeQueryInfo relFieldName arrayNullability objectRelDesc
pure pure
$ nativeQueryParser $ nativeQueryParser
<&> \selectExp -> <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) selectExp $ IR.AnnRelationSelectG (riName ri) (riMapping ri) innerNullability selectExp
RelTargetTable _otherTableName -> do RelTargetTable _otherTableName -> do
throw500 "Array relationships from logical models to tables are not implemented" throw500 "Array relationships from logical models to tables are not implemented"
logicalModelArrayRelationshipField _ _ _ = logicalModelArrayRelationshipField _ _ _ _ =
hoistMaybe Nothing -- the target logical model expected an array relationship, but this was an object hoistMaybe Nothing -- the target logical model expected an array relationship, but this was an object

View File

@ -292,7 +292,7 @@ convExtRel sqlGen fieldInfoMap relName mAlias selQ sessVarBldr prepValBldr = do
when misused $ throw400 UnexpectedPayload objRelMisuseMsg when misused $ throw400 UnexpectedPayload objRelMisuseMsg
pure pure
$ Left $ Left
$ AnnRelationSelectG (fromMaybe relName mAlias) colMapping $ AnnRelationSelectG (fromMaybe relName mAlias) colMapping Nullable
$ AnnObjectSelectG (_asnFields annSel) (FromTable relTableName) $ AnnObjectSelectG (_asnFields annSel) (FromTable relTableName)
$ _tpFilter $ _tpFilter
$ _asnPerm annSel $ _asnPerm annSel
@ -303,6 +303,7 @@ convExtRel sqlGen fieldInfoMap relName mAlias selQ sessVarBldr prepValBldr = do
$ AnnRelationSelectG $ AnnRelationSelectG
(fromMaybe relName mAlias) (fromMaybe relName mAlias)
colMapping colMapping
Nullable
annSel annSel
where where
pgWhenRelErr = "only relationships can be expanded" pgWhenRelErr = "only relationships can be expanded"

View File

@ -18,6 +18,7 @@ module Hasura.RQL.IR.Select.Lenses
aarAnnSelect, aarAnnSelect,
aarColumnMapping, aarColumnMapping,
aarRelationshipName, aarRelationshipName,
aarNullable,
anosSupportsNestedObjects, anosSupportsNestedObjects,
anosColumn, anosColumn,
anosFields, anosFields,

View File

@ -12,12 +12,14 @@ import Hasura.Prelude
import Hasura.RQL.Types.Backend import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Relationships.Local (Nullable)
-- Local relationship -- Local relationship
data AnnRelationSelectG (b :: BackendType) a = AnnRelationSelectG data AnnRelationSelectG (b :: BackendType) a = AnnRelationSelectG
{ _aarRelationshipName :: RelName, -- Relationship name { _aarRelationshipName :: RelName, -- Relationship name
_aarColumnMapping :: HashMap (Column b) (Column b), -- Column of left table to join with _aarColumnMapping :: HashMap (Column b) (Column b), -- Column of left table to join with
_aarNullable :: Nullable, -- is the target object allowed to be missing?
_aarAnnSelect :: a -- Current table. Almost ~ to SQL Select _aarAnnSelect :: a -- Current table. Almost ~ to SQL Select
} }
deriving stock (Functor, Foldable, Traversable) deriving stock (Functor, Foldable, Traversable)