I started to use rel8 not so long time ago and there is still a lot of new for me. Maybe I just didn't found an answer in ;documentation or maybe there is no such option for now.
But I have feeling that what I do should be in a bit different way. So, hope you can make it clear for me.
1) Often I want to insert a single row to table and I want my function to return that created row:
I need Maybe here, because createTeamRoleQ is part of transaction:
createTeam
:: (WithDb m, WithError m)
=> AccountPk
-> TeamScopePk
-> TeamName
-> m TeamR
createTeam aPk teamScopePk name =
-- throw error on top level of computation
throwOnNothingM Logger.Error (ApiError "can't get team in response")
. Db.runTransaction
$ runMaybeT
( do
-- create team
team <- MaybeT insertTeam
-- create default team roles
roles <- mapM (MaybeT . createTeamRoleQ team) defaultTeamRoleNames
guard $ length defaultTeamRoleNames == length roles
-- assign creator to created roles
assignees <- mapM (MaybeT . assignToTeamRoleQ aPk) roles
guard $ length defaultTeamRoleNames == length assignees
pure team
)
-- rollback transaction in case on any step Nothing occurs
>>= maybe (Sql.condemn >> pure Nothing) (pure . pure)
where
insertTeam :: Sql.Transaction (Maybe TeamR)
insertTeam =
fmap listToMaybe
. Sql.statement ()
. Sql.insert
$ Sql.Insert
{ into = teamSchema
, rows =
Sql.values
[ Team
{ tTeamPk = Sql.nextPk teamSchema
, tTeamScopePk = Sql.lit teamScopePk
, tInitiatorPk = Sql.lit aPk
, tName = Sql.lit name
}
]
, onConflict = Sql.Abort
, returning = Sql.Projection id
}
In this example I apply listToMaybe en each Insert statement to convert list to Maybe value, and in case on some step there is Nothing - I rollback whole transaction.
In terms of types it seems correct, but in fact I want to get not even Maybe TeamRoleR but single TeamRoleR, this way I do not need to apply all this listToMaybe and there is no need in MaybeT.
I've tried to replace Sql.values with pure, but I still have list in result type.
What do you think about it?
2) Second concern is about Select
Yes, it's seems natural to get list on Select query, but there is some cases:
when we use Sql.limit 1
This case we want to get single value, so more natural here will be to return Maybe - I solved it by defining helper
selectOne
:: forall exprs a
. (Serializable exprs a)
=> Query exprs
-> Statement () (Maybe a)
selectOne = fmap listToMaybe . Sql.limit 1
{-# INLINE selectOne #-}
when we use Sql.exists we expect that
Checks if a query returns at least one row.
and then to execute it we use Sql.select again and receive list of Bool
I solved it by defining another helper:
Hello.
I started to use
rel8
not so long time ago and there is still a lot of new for me. Maybe I just didn't found an answer in ;documentation or maybe there is no such option for now.But I have feeling that what I do should be in a bit different way. So, hope you can make it clear for me.
1) Often I want to insert a single row to table and I want my function to return that created row:
but by default what I can get is
so, what I usually do - is just applying
listToMaybe
to result like this:I need
Maybe
here, becausecreateTeamRoleQ
is part of transaction:In this example I apply
listToMaybe
en eachInsert
statement to convert list toMaybe
value, and in case on some step there is Nothing - I rollback whole transaction. In terms of types it seems correct, but in fact I want to get not evenMaybe TeamRoleR
but singleTeamRoleR
, this way I do not need to apply all thislistToMaybe
and there is no need inMaybeT
.I've tried to replace
Sql.values
withpure
, but I still have list in result type. What do you think about it?2) Second concern is about
Select
Yes, it's seems natural to get list onSelect
query, but there is some cases:Sql.limit 1
This case we want to get single value, so more natural here will be to returnMaybe
- I solved it by defining helperSql.exists
we expect thatand then to execute it we use
Sql.select
again and receive list ofBool
I solved it by defining another helper:Maybe I'm missing something but I want to understand whether I'm using your library in right way. Thanks.