-
Notifications
You must be signed in to change notification settings - Fork 48
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
Support returning
in rows_*.tbl_dbi()
#607
Conversation
Thanks. Should we discuss conditional updates and mutating joins separately? |
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.
Thanks, this is a good start.
I think type stability for the return values is really important here. Can we return the inserted rows in an attribute to the returned table?
Please also run |
You mean something like returned_rows <- dbGetQuery(con, sql, immediate = TRUE)
attr(x, "returned_rows") <- returned_rows
invisible(x) and then have a helper function e.g. I can do that and I think type stability is important. On the other hand it also seems a bit counterintuitive to me. The In case you have a pipeline of insert/update/upsert operations in mind, i.e. x %>%
dm::rows_insert(y, returning = "id") %>%
dm::rows_insert(y2, returning = "id") %>%
dm::rows_update(z, returning = "id") it might make sense that the user could choose the name of the attribute so that all results from returning can still be accessed. |
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.
Thanks. Can we simplify further?
R/rows-db.R
Outdated
sql <- sql_rows_insert(x, y) | ||
dbExecute(con, sql, immediate = TRUE) | ||
invisible(x) | ||
sql <- sql_rows_insert(x, y, returning = returning) |
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.
Do we really need to pass returning
to the sql_()
methods?
sql <- sql_rows_insert(x, y, returning = returning) | |
sql <- paste0( | |
sql_rows_insert(x, y, returning = returning) | |
if (!is.null(returning)) paste0("\n", sql_returning(...)) | |
) |
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.
If returning
is not an argument of the sql_()
methods then I would rather have something like
sql_rows_insert(x, y, returning = returning) %>%
sql_add_returning(x, returning)
and export sql_add_returning()
(this should be exported to complete the other sql functions). To me this feels like a more user-friendly interface. What do you think?
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.
I think we need an sql_returning()
generic anyway -- to special-case both the clause and the way column expressions are constructed (to work around that RSQLite bug). I don't mind sql_add_returning()
as an equivalent to the paste0()
call in my proposal.
Thanks, the attribute looks good. Regarding stacking of "returning" data, I think it's dangerous to use the pipe for functions that have side effects: x %>%
dm::rows_insert(y, returning = "id", in_place = TRUE) %>%
dm::rows_insert(y2, returning = "id", in_place = TRUE) %>%
dm::rows_update(z, returning = "id", in_place = TRUE) If the first call succeeds but the second call fails, you might be tempted to re-run the pipe, which might now also fail the first call. It's safer to un-pipe this and consume return values implicitly. I don't think we need to act here. |
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.
Thanks, a few final nitpicks.
For tests of this feature, we can use persistent tables, referring to the blocking issue. If you could add them, I'll start the CI run and merge.
I think it should be sufficient to rely on the dev version of RSQLite as the bug is fixed in there. |
RSQLite 2.2.8 is on CRAN now. |
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.
Thanks, looks great! Running checks now, one last question.
We need |
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.
Thanks, this is huge! Looking forward to using it.
I love SQL Server... |
Thanks! |
Closes #593.
dbGetQuery()
returns no columns for INSERT ... RETURNING on temporary tables r-dbi/RSQLite#380 and hindered byRETURNING
produces wrong column name r-dbi/RSQLite#381.dbplyr
functionsident()
andescape()
dplyr::rows_update()
doesn't have an argumentreturning
but nowrows_update.tbl_dbi()
has it. To use the tidyselect interface Ienquo()
. This doesn't work with thecheck_dots_used()
used in the generic.