
On Sun, Aug 31, 2025 at 8:44 AM Maximilian Riemensberger via Boost < boost@lists.boost.org> wrote:
Hi,
First, I want to thank Klemens Morgenstern for his work on this library and proposing it to boost, and Mohammad Nejati for managing the review.
I have started to look at a the library from a user's perspective with limited sqlite3 experience. I ran into a few issues, where I would like to understand the rationale behind some of the design decisions:
Thank you for participating in the review process.
* The field type returns sqlite TEXT data as cstring_ref instead of string_view. The sqlite documentation guarantees it's NUL terminated, but it also recommends using e.g. sqlite3_column_bytes to determine the length of text data and does not explicitly forbid embedded NUL characters.
I would recommend using the blob interface then. A string_view with null-terminators in the middle is also generally bad news.
* The connection type can be owning or non-owning. Why wouldn't one instead have distinct connection (owning) and connection_ref (non-owning) types?
Because otherwise the complexity goes up unnecessarily. A user can write a
function just taking `connection&` and not worry about this. In the library I have the `transaction` type for example. It holds a reference to the connection - if there was a second type like `connection_ref`, now I would have a second type of a transaction. I could of course add a connection_base and build a OOP construct, but that would just be a more inefficient & cumbersome version of the current solution.
* The statement type can construct owning and non-owning resultsets. The former automatically finalize, the latter reset the statement. Again why are those two behaviors combined in the same type?
Same reason as above. If a user wrote a manual converter for each row, he'd need to implement it twice. The point is that those two things just work:
T interpret_result(sqlite::resultset rs); auto rr = interpret_result(conn.prepare("...").execute(...)); auto s = conn.prepare("..."); auto r2 = interpret_result(s.execute(...)); Why should I force a user to write two different implementations of interpret_result? And the answer isn't OOP for the resultset, because that it cannot be passed by value.
* The library is designed around unique_ptr wrapping the sqlite3 C API handles with optional ownership. In particular, this seems at times quite dangerous for the sqlite3_stmt handle which is shared by statement, resultset, field, etc. Would the library be better served by for example reference counting such handles? If not, why?
There is no obvious place to put the counter. If sqlite had those, I'd use them.
* What is the general thread safety guarantees of the library types? After all, it contains a mutex implementation wrapper. So multi-threaded application are probably a target for this library.
Same as whatever sqlite is compiled for.
Best regards Max
_______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/UQV5X5HL...