mkFromSql :: PrimaryKey key -> RelationalMap a b -> FromSql b
mkFromSql (PrimaryKey pKeyPart pKeyParts) relMap =
  fromSql
    { runFromSql = \columns ->
        -- lookup the primary key columns
        let keyNames = map getColName (pKeyPart : pKeyParts)
            primKeys = filter ((`elem` keyNames) . fst) columns

         in case runFromSql fromSql columns of
              -- Add the primary key(s) to relevant error messages
              Left (RowDataError details) ->
                Left $ RowDataError details
                         { rowErrorPrimaryKeys = primKeys }

              Left (ConversionError details) ->
                Left $ ConversionError details
                         { convErrorPrimaryKeys = primKeys }

              x -> x
    }
  where
    fromSql = fromRelMap relMap

    getColName (PrimaryKeyPart _ fieldDef) = fieldName fieldDef

    fromRelMap :: RelationalMap a b -> FromSql b
    fromRelMap (RM_Field field) = fieldFromSql field
    fromRelMap (RM_Nest _ rm) = fromRelMap rm
    fromRelMap (RM_ReadOnly rm) = fromRelMap rm
    fromRelMap (RM_MaybeTag rm) = fromRelMap rm
    fromRelMap (RM_Pure b) = pure b
    fromRelMap (RM_Apply rmF rmC) = fromRelMap rmF <*> fromRelMap rmC
    fromRelMap (RM_Partial rm) = do
      joinFromSqlError (wrapError <$> fromRelMap rm)
    wrapError = either (Left . simpleConversionError) Right
mkFromSql :: PrimaryKey key -> RelationalMap a b -> FromSql b
mkFromSql (PrimaryKey pKeyPart pKeyParts) relMap =
  fromSql
    { runFromSql = \columns ->
        -- lookup the primary key columns
        let keyNames = map getColName (pKeyPart : pKeyParts)
            primKeys = filter ((`elem` keyNames) . fst) columns

         in case runFromSql fromSql columns of
              -- Add the primary key(s) to relevant error messages
              Left (RowDataError details) ->
                Left $ RowDataError details
                         { rowErrorPrimaryKeys = primKeys }

              Left (ConversionError details) ->
                Left $ ConversionError details
                         { convErrorPrimaryKeys = primKeys }

              x -> x
    }
  where
    fromSql = fromRelMap relMap

    getColName (PrimaryKeyPart _ fieldDef) = fieldName fieldDef

    fromRelMap :: RelationalMap a b -> FromSql b
    fromRelMap (RM_Field field) = fieldFromSql field
    fromRelMap (RM_Nest _ rm) = fromRelMap rm
    fromRelMap (RM_ReadOnly rm) = fromRelMap rm
    fromRelMap (RM_MaybeTag rm) = fromRelMap rm
    fromRelMap (RM_Pure b) = pure b
    fromRelMap (RM_Apply rmF rmC) = fromRelMap rmF <*> fromRelMap rmC
    fromRelMap (RM_Partial rm) = do
      joinFromSqlError (wrapError <$> fromRelMap rm)
    wrapError = either (Left . simpleConversionError) Right
mkFromSql (PrimaryKey pKeyPart pKeyParts) relMap =
  fromSql
    { runFromSql = \columns ->
        -- lookup the primary key columns
        let keyNames = map getColName (pKeyPart : pKeyParts)
            primKeys = filter ((`elem` keyNames) . fst) columns

         in case runFromSql fromSql columns of
              -- Add the primary key(s) to relevant error messages
              Left (RowDataError details) ->
                Left $ RowDataError details
                         { rowErrorPrimaryKeys = primKeys }

              Left (ConversionError details) ->
                Left $ ConversionError details
                         { convErrorPrimaryKeys = primKeys }

              x -> x
    }
  where
    fromSql = fromRelMap relMap

    getColName (PrimaryKeyPart _ fieldDef) = fieldName fieldDef

    fromRelMap :: RelationalMap a b -> FromSql b
    fromRelMap (RM_Field field) = fieldFromSql field
    fromRelMap (RM_Nest _ rm) = fromRelMap rm
    fromRelMap (RM_ReadOnly rm) = fromRelMap rm
    fromRelMap (RM_MaybeTag rm) = fromRelMap rm
    fromRelMap (RM_Pure b) = pure b
    fromRelMap (RM_Apply rmF rmC) = fromRelMap rmF <*> fromRelMap rmC
    fromRelMap (RM_Partial rm) = do
      joinFromSqlError (wrapError <$> fromRelMap rm)
    wrapError = either (Left . simpleConversionError) Right