1. Can `Box<dyn RowAccessor>` even work like that, considering it's not object safe? My understanding is that adding the `Self:Sized` bound to `get` makes it compile, but also means that this method won't be available in a dynamic context, so the accessor you get from the rowset is completely useless.<p>2. Why do the accessors return results? IO errors should already happen when loading into the rowset. So at that point the only error the column accessor could run into is an out of bounds index, which is a panic worthy programming error.<p>3. Why do the accessors return options? Shouldn't that be absorbed into the generic `T` and only be used for nullable columns?<p>4. Why return owned accessors (boxes) instead of references?<p>5. Columnar datastorage without any low level access to the in-memory representation seems rather pointless, for a performance point of view. You can't access it with SIMD instructions and incur an indirect call overhead for each accessed element. Do you expect people to downcast the column accessor to a specific type for high performance access?<p>IMO abstracting over storage formats via dynamic dispatch is the wrong approach. The proper way is making all types take a generic a parameter for the format.
I appreciate that the author here takes pains to review existing standards and implementations like ODBC/JDBC, and also reviews newer ideas like columnar stores and projects like Apache Arrow. It inspires confidence when I see engineers do some degree of review before swashbuckling their way into new code. It’s like the literature review in graduate school: first read, then code.
There are also other projects working solving similar problems.<p>The other is sqlx[0] serving as an asynchronous crate connecting to mysql and postgresql that validates the queries at compile time and is built as a new ground-up implementation using async/await and async-std.<p>And our project is quaint[1] which builds on top of existing tokio-based database crates giving a unified interface and a query builder.<p>[0] <a href="https://crates.io/crates/sqlx" rel="nofollow">https://crates.io/crates/sqlx</a>
[1] <a href="https://crates.io/crates/quaint/" rel="nofollow">https://crates.io/crates/quaint/</a>
I've never understood the appeal of this sort of thing. The idea is create a common interface to a bunch of different databases. But you still have to write or generate SQL that is specific to whatever database you're actually using. Outside of a very narrow range of apps (eg SQL-IDE kinds of tools), you're going to be both coupled to a specific database and limited by lowest-common-denominator design constraints in the interface library. Ugh.
I think the initiative is great. I did lots of Java database development. Starting with JDBC, circumventing J2EE with Spring and Hibernate, and ending up doing JPA with Spring. I haven't seen anything similar in Rust.<p>Therefore I recommend looking at JPA for object relational mapping, and Spring Frameworks JdbcTemplate for things like basic CRUD support and JPA abstraction.
The work made by this guy is incredible.
Apache arrow commiter (Datafusion), wrote SQL crate, BAllista (think spark+k8s-java+rust), and now this.<p>I feel too much envy.
> RDBC is specifically for the use case where a developer needs the ability to execute arbitrary SQL against any database and then be able to fetch the results.<p>So RDBC solves the problem of different connection protocols. But what do you do about the fact that writing a query that works for every database is extremely difficult?
Efficient access is more than the interface on the client. The wire format matters. If the server sends the data in the row form from a columnar stored table in row form, it wont be efficient, there will be too many transformations. Perhaps a way for the client to tell the server what format it wants the data may be useful.
Why not use macros to map the result back? I understand that that is not consistent with jdbc and may be crossing into ORM territory, but it does seem like a clean way to handle it in rust.