nbenn opened a new issue, #4820:
URL: https://github.com/apache/arrow-adbc/issues/4820

   Executed without a result stream, a statement that changes no rows reports 
the row count of the previous `INSERT`, `UPDATE` or `DELETE` in the SQLite 
driver. With the driver built from `main` at f1378d6 against SQLite 3.45.1:
   
   ```r
   library(adbcdrivermanager)
   db <- adbc_database_init(adbc_driver("adbc_driver_sqlite"), uri = ":memory:")
   con <- adbc_connection_init(db)
   execute <- function(sql) {
     stmt <- adbc_statement_init(con)
     on.exit(adbc_statement_release(stmt))
     adbc_statement_set_sql_query(stmt, sql)
     adbc_statement_execute_query(stmt)
   }
   execute("CREATE TABLE t (a INTEGER)")
   #> [1] 0
   execute("INSERT INTO t VALUES (1), (2), (3)")
   #> [1] 3
   execute("CREATE TABLE u (b INTEGER)")
   #> [1] 3
   execute("DROP TABLE u")
   #> [1] 3
   ```
   
   The update path adds `sqlite3_changes()` for every statement without result 
columns 
([source](https://github.com/apache/arrow-adbc/blob/f1378d664b61ce65f25a54c3b863aa62ea9d2480/c/driver/sqlite/sqlite.cc#L1127-L1129)),
 and `sqlite3_changes()` returns the count of the most recent completed 
`INSERT`, `UPDATE` or `DELETE`, which other statements leave unchanged 
([docs](https://www.sqlite.org/c3ref/changes.html)). It came up in adbi, which 
runs statements with a result stream and so gets `-1` from every one of them 
(r-dbi/adbi#92); running them without a stream fixes that, but passes these 
counts on for DDL.
   
   RSQLite avoids this by taking the difference in `sqlite3_total_changes()` 
across the statement 
([source](https://github.com/r-dbi/RSQLite/blob/201287ef6db6dce4d5c3e13b1ae6453ea0f570f3/src/SqliteResultImpl.cpp#L123)).
 Counting `sqlite3_changes()` only when that total moved does the same here:
   
   ```diff
   +      const int total_changes = sqlite3_total_changes(conn_);
          while (sqlite3_step(stmt_) == SQLITE_ROW) {
            output_rows++;
          }
    
   -      if (sqlite3_column_count(stmt_) == 0) {
   +      if (sqlite3_column_count(stmt_) == 0 &&
   +          sqlite3_total_changes(conn_) != total_changes) {
            changed_rows += sqlite3_changes(conn_);
          }
   ```
   
   With that change, the `CREATE TABLE` and `DROP TABLE` above report 0, as 
does a `CREATE INDEX`. The DML counts I checked stay as they were: 3 for an 
`INSERT` of 3 rows whose trigger inserts 3 more, 3 for a bound `INSERT` of 3 
rows, 0 for an `UPDATE` that matches no rows, and 5 for a `DELETE` of 5. I have 
not run the driver's test suite with it. I can open a PR.
   
   This report was drafted with an AI assistant; the code above was run as 
shown.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to