我一直在尝试在项目中使用 Opaleye 运行左连接,但无法编译代码。我从两个代表关联表的“模型”开始:
第一的:
data ModelA' a b = Model { primA :: a, foreignA :: b }
type ModelA = ModelA' UUID UUID
type ModelAColumn = ModelA' (Column PGUuid) (Column (Nullable PGUuid))
$(makeAdaptorAndInstance "pModelA" ''ModelA')
table :: Table ModelAColumn ModelAColumn
table = Opaleye.table "model_a" $ pModelA (ModelA (tableColumn "uuid") (tableColumn "foreign"))
并且:
data ModelB' a b = Model { primB :: a, valB :: b }
type ModelB = ModelB' UUID String
type ModelBColumn = ModelB' (Column PGUuid) (Column PGText)
$(makeAdaptorAndInstance "pModelB" ''ModelB')
table :: Table ModelBColumn ModelBColumn
table = Opaleye.table "model_b" $ pModelB (ModelB (tableColumn "uuid") (tableColumn "val"))
正如类型所反映的,ModelA可以没有关联的ModelB。
我需要一个查询来获取由foreignA == primB上的表之间的左连接给出的(ModelA,Maybe ModelB)对。我期待它看起来像:
doJoin :: Connection -> IO [(ModelA, Maybe ModelB)]
doJoin conn = runQuery conn query
where
query :: Query (ModelAColumn, Maybe ModelBColumn)
query = leftJoin (queryTable ModelA.table) (queryTable ModelB.table) (\(ma, mb) -> foreignA ma .== primB mb)
但这不起作用。我还尝试了多种变体,特别是我替换了查询中的类型签名以明确说明右侧列的可空性:
query :: Query (ModelAColumn, (Column (Nullable PGUuid), Column (Nullable PGText))
但这失败了:
Data.Profunctor.Product.Default.Class.Default Opaleye.Internal.Join.NullMaker ModelBColumn 没有实例(列(可空 PGUuid),列(可空 PGText)。
如何在 Opaleye 中进行此查询?