ncruces / go-sqlite3

Go bindings to SQLite using wazero
https://pkg.go.dev/github.com/ncruces/go-sqlite3
MIT License
402 stars 12 forks source link

More APIs. #125

Closed ncruces closed 1 month ago

ncruces commented 1 month ago

Will wrap these before the next release.

These should be easy:

sqlite3_trace_v2 raises interesting questions. It'd be a second "constructor" for *sqlite3.Stmt, which raises the question of pointer identity. If we want two *sqlite3.Stmt to be equal, we need to dedup them, which means storing a list of them in *sqlite3.Conn (which incidentally SQLite also does). We'd also probably need identity, to make it easier to trace the start/row/end moments of a *sqlite3.Stmt run.

If we do this, we can also iterate over statements in a connection (replacing sqlite3_next_stmt), and sqlite3_sql and sqlite3_expanded_sql can also start to make sense.


These are also done:

ncruces commented 1 month ago

See #126.

ncruces commented 1 month ago

sqlite3_trace_v2 is half done, and looking good enough for closure notification: it's called just before the connection being closed (which allows running PRAGMA optimize on closure, etc).

Need to work on deduping the *sqlite.Stmt pointers.

PS: There's an additional challenge. Statements we Exec also get a "native" prepared statement, but those are "finalized" immediately after the Exec ends. Deduping those (and the SQL string) to make them traceable, and avoid a bunch of memory churn is complicated; not sure it's feasible.

daenney commented 1 month ago

sqlite3_trace_v2 is half done, and looking good enough for closure notification: it's called just before the connection being closed (which allows running PRAGMA optimize on closure, etc).

Taking a bit of creative license with how trace is used works for me :smile:. The only thing I'm wondering is if people will take exception to it because trace sounds like something that has the potential for performance impact.

ncruces commented 1 month ago

This is pretty much wrapped up now.

Documenting decisions.

I decided that only statements explicitly prepared from Go will be traced. This is unlike SQLite, but it is the only way to make pointer identity/equality work, as long as Go does not have weak references. Traces about statements that weren't prepared from Go are simply ignored (this means Execed statements, but also statements executed by native virtual tables, like FTS5).

So far, I haven't exposed sqlite3_next_stmt (I'd rather expose a Go 1.23 sequence of statements), nor sqlite3_sql (I'd probably rather keep the Go string around than rematerialize it every time), nor sqlite3_expanded_sql. Right now, TRACE_STMT allocs a copy of the SQL string every time.

Until Go has some form of interning (for strings, and objects) or weak references, which both seem unlikely (package unique is no replacement) this is unlikely to change. The only alternative I see is to make sqlite3.Stmt a value, not a pointer, but that's bad too (because Close clears the handle).