-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Statements overhaul (support for statement-level WITH
)
#250
Conversation
@ocharles This is what I had in mind when I first mentioned turning I do insist on I don't like that in your approach we end up with three versions of everything ( Also note that your Also, your API doesn't provide a way to get the number of rows affected by an But this does address your other concerns in your comment on the first PR — there's no |
First, let me quickly reply to some of your comments.
I did consider this but actually thought that it would work, but didn't test it. I was kind of hoping that the internal
Not directly, but people could just
There's another slightly different point here. I again considered this, but considered it a pretty fringe scenario. Your example is better written with just In summary, your comments about my last approach all valid, though I did consider them and basically considered them an acceptable trade-off. But they are a trade-off, and as your PR shows, we don't have to make that trade off. Now, on to this PR. Thanks for spending a bit more time on it. I like this approach a lot more. A legitimate data Rows = Void | ..
run :: Rows a -> ... into run_ :: Statement exprs -> Hasql.Statement () ()
runN :: Statement () -> Hasql.Statement () Int64
runOne :: Serializable exprs a => Statement (Query exprs) -> Hasql.Statement () a
runMaybe :: Serializable exprs a => Statement (Query exprs) -> Hasql.Statement () (Maybe a)
run :: Serializable exprs a => Statement (Query exprs) -> Hasql.Statement () [a]
runVector :: Serializable exprs a => Statement (Query exprs) -> Hasql.Statement () (Vector a) (We could also lose the uniform What do you think about this? I suggest this because I still think the most common use-case of Rel8 is a single select, and I would much prefer to write run $ select do
... over run List $ select do
... Minor, but a tiny bit more convenient. I don't really see anything else that a user would care about Other than deciding on this last point, I think we're all good! |
Yeah, I can live with hiding the explicit |
d30d247
to
661f221
Compare
661f221
to
68cbac1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, and thanks for working with me to refine this PR!
The motivation behind this PR is to add support for PostreSQL's `WITH` syntax at the statement level, which gives the ability to, e.g., delete some rows from a table and then re-insert those deleted rows into another table, without any round-trips between the application and the database. To support this, this PR introduces a new type called `Statement`, which represents a single PostgreSQL statement. It has a `Monad` instance which allows sub-statements (such as `DELETE` and `INSERT` statements) to be composed together and their results bound to values that can be referenced in subsequent sub-statements. These "compound" statements are then rendered as a `WITH` statement. `select`, `insert`, `update` and `delete` have all been altered to produce the `Statement` type described above instead of the `Hasql.Statement` type. Some changes were necessary to the `Returning` type. `Returning` previously bundled two different concepts together: whether or not to generate a `RETURNING` clause in the SQL for a manipulation statement, and how to decode the returned rows (if any). It was necessary to break these concepts apart because with `WITH` we need the ability to generate manipulation statements with `RETURNING` clauses that are never actually decoded at all (the results just get passed to the next statement without touching the application). Now, the `Returning` type is only concerned with whether or not to generate a `RETURNING` clause, and the question of how to decode the returned the result of the statement is handled by the `run` functions. `run` converts a `Statement` into a runnable `Hasql.Statement`, decoding the result of the statement as a list of rows. The other variations, `run_`, `runN`, `run1`, `runMaybe` and `runVector` can be used when you want to decode as something other than a list of rows. This also gains us support for decoding the result of a query directly to a `Vector` for the first time, which brings a performance improvement over lists for those who need it.
68cbac1
to
f1402ad
Compare
The motivation behind this PR is to add support for PostreSQL's
WITH
syntax at the statement level, which gives the ability to, e.g., delete some rows from a table and then re-insert those deleted rows into another table, without any round-trips between the application and the database.To support this, this PR introduces a new type called
Statement
, which represents a single PostgreSQL statement. It has aMonad
instance which allows sub-statements (such asDELETE
andINSERT
statements) to be composed together and their results bound to values that can be referenced in subsequent sub-statements. These "compound" statements are then rendered as aWITH
statement.select
,insert
,update
anddelete
have all been altered to produce theStatement
type described above instead of theHasql.Statement
type.Some changes were necessary to the
Returning
type.Returning
previously bundled two different concepts together: whether or not to generate aRETURNING
clause in the SQL for a manipulation statement, and how to decode the returned rows (if any). It was necessary to break these concepts apart because withWITH
we need the ability to generate manipulation statements withRETURNING
clauses that are never actually decoded at all (the results just get passed to the next statement without touching →Now, the
Returning
type is only concerned with whether or not to generate aRETURNING
clause, and the question of how to decode the returned the result of the statement is handled by therun
functions.run
converts aStatement
into a runnableHasql.Statement
, decoding the result of the statement as a list of rows. The other variations,run_
,runN
,run1
,runMaybe
andrunVector
can be used when you want to decode as something other than a list of rows.This also gains us support for decoding the result of a query directly to a
Vector
for the first time, which brings a performance improvement over lists for those who need it.