Statements overhaul (support for statement-level WITH)#250
Statements overhaul (support for statement-level WITH)#250shane-circuithub merged 1 commit intomasterfrom
WITH)#250Conversation
|
@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
ocharles
left a comment
There was a problem hiding this comment.
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
WITHsyntax 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 aMonadinstance which allows sub-statements (such asDELETEandINSERTstatements) 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 aWITHstatement.select,insert,updateanddeletehave all been altered to produce theStatementtype described above instead of theHasql.Statementtype.Some changes were necessary to the
Returningtype.Returningpreviously bundled two different concepts together: whether or not to generate aRETURNINGclause 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 withWITHwe need the ability to generate manipulation statements withRETURNINGclauses that are never actually decoded at all (the results just get passed to the next statement without touching →Now, the
Returningtype is only concerned with whether or not to generate aRETURNINGclause, and the question of how to decode the returned the result of the statement is handled by therunfunctions.runconverts aStatementinto a runnableHasql.Statement, decoding the result of the statement as a list of rows. The other variations,run_,runN,run1,runMaybeandrunVectorcan 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
Vectorfor the first time, which brings a performance improvement over lists for those who need it.