Skip to content
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

Streaming multiple statements in a single dbExecute/dbQuery/etc. call #56

Open
mmuurr opened this issue Feb 11, 2022 · 1 comment
Open

Comments

@mmuurr
Copy link

mmuurr commented Feb 11, 2022

This was mentioned a few years back in r-dbi/RPostgres#152 and I simply failed to actually start the conversation over here. It'd be very useful to be able to place multiple SQL statements in a single file then send that to the DB backend. I've had cryptic failures with both RMariaDB and RPostgres when wanting to do something akin to:

DBI::dbExecute(conn, readr::read_file("my-sql-script.sql"))

... and perhaps mixed-in with other DBI utilities and single-statement constructs, like:

DBI::dbWithTransaction(conn, {
  DBI::dbExecute(conn, readr::read_file("my-sql-script.sql"))  ## <-- as an example, this multi-statement script may create _my_temp_table
  DBI::dbGetQuery(conn, "select * from _my_temp_table")  ## <-- single statement
  ## some other application code
})

As a further-motivating case, consider where "my-sql-script.sql" is a {glue} template, so:

DBI::dbExecute(conn, glue::glue_sql(readr::read_file("my-sql-script.sql"), .con = conn))

The {glue} example helps address the 'what to do for parameterized statements' question: in essence, nothing ... in fact if there was something like dbExecuteBatch() that simply didn't permit driver-managed parameterization, I think that'd be great. Any interpolation needed can be handled by {glue} or other string-based methods (with all the associated buyer-beware injection-attack caveats).

With the current single-statement implementations, one can rip apart a script into multiple statements, but many SQL scripts are quite long (at least in my case). Ripping apart the script into lots of separate files thus isn't a great option, nor is littering the R code with a lot of SQL string literals, especially when the SQL file is useful on its own (i.e. as a standalone script to be used by other programs or users).

One could try to parse the file and separate out the individual statements, then iterate over them, like:

readr::read_file("my-sql-script.sql") %>%
  sqlparser::parse_into_separate_statements() %>%  ## <-- an imaginary package & function
  purrr::walk(function(x) DBI::dbExecute(conn, x))

... but that requires an actual SQL-parsing step, which seems best left to the SQL driver/engine itself.

As noted in r-dbi/RPostgres#152, PostgreSQL supports this via the use of PQexec() (vs PQprepare() for single statements).

@krlmlr krlmlr transferred this issue from r-dbi/DBI Apr 14, 2022
@krlmlr
Copy link
Member

krlmlr commented Apr 14, 2022

Thanks for raising this. We should consider offering a way to run multi-statement nonparameterized scripts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants