Hey.
Disclaimer: I am an experienced dev, but new to Rust. I've built a bunch of pet projects with it. SQL (and Sqlite) are old hats.
I thought I'd write a quick silly web app today, a rewrite of a thing I did in another language. How hard could it be? Well, I got stuck for hours with the worst error messages I've seen in rust land so far and .. haven't solved the most basic "Read data from a single table" use case yet.
I am using Sqlite, because it's a tiny container and I don't want another service. Diesel claims it supports MySQL, Postgres and Sqlite... but does it?
My table structure over in the other ecosystem translates to
CREATE TABLE
hosts
(
id
TEXT NOT NULL, -- This is a UUID
created_at
TEXT NOT NULL
-- a bunch of other things
)
#[derive(Queryable)]
pub struct Host {
pub id: UUID,
pub created_at: Timestamp,
// more stuff
}
actually created_at is an INTEGER and a unix timestamp, but .. bear with me.
The error messages make zero sense and don't explain what the problem is. In the table above? After hours of frustration I found the "wontfix" bug saying that Diesel does have a uuid feature flag, but .. that only works for one of the "supported" databasesÂą. Okay, that's unfortunate and really not great UX (especially because the error messages don't contain anything of value). The workarounds mentioned in that ticket don't work anymore since diesel reached 2.x, but with a bit of patience and browsing the docs some more (it seems Sqlite is really a step child here) I am able to .. read and write uuids after just a few hours. Progress!
Let's uncomment the next fields in my table. Fast forward and another couple hours later I'm unsure what the solution is to get basic "serialize timestamps" to work. For reasons I cannot understand Timestamp (and Date/DateTime) maps to TEXT for Sqlite (why?) and I've tried gazillion combinations of mapping my schema with a simple TEXT NOT NULL to .. Timestamp. Or chrono::NaiveDateTime .. and whatever else came to mind. The error messages are again completely opaque and not helping. I'm at the verge of adding my own custom serialization similar to the UUID workaround .. but that can't be the way?
TL/DR: 6-8 hours in I'm unable to use Diesel with a single, simple, trivial table in Sqlite. Am I dumb? Maybe. But I could've done this a few minutes in most other stacks. What am I missing, what can I do to improve the situation? I must be overlooking something huge to get stuck this hard or Sqlite support is seriously broken. Would appreciate pointers to
a) help me understand the uuid mess
b) solve the timestamp situation
c) learning material that make all these things click or turn the diesel error messages² into something helpful
①: Add support for Uuid to SQLite · Issue #364 · diesel-rs/diesel · GitHub
②:
error[E0277]: the trait bound `(diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Text, Nullable<diesel::sql_types::Text>): load_dsl::private::CompatibleType<foo::models::Host, _>` is not satisfied
--> src/main.rs:13:38
|
13 | let results = hosts.load::<Host>(connection).expect("Error loading hosts");
| ---- ^^^^^^^^^^ the trait `load_dsl::private::CompatibleType<foo::models::Host, _>` is not implemented for `(diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Text, Nullable<diesel::sql_types::Text>)`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `load_dsl::private::CompatibleType<U, DB>`:
(ST0, ST1)
(ST0, ST1, ST2)
(ST0, ST1, ST2, ST3)
(ST0, ST1, ST2, ST3, ST4)
(ST0, ST1, ST2, ST3, ST4, ST5)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7)
(ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8)
and 24 others
= note: required for `table` to implement `LoadQuery<'_, _, foo::models::Host>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/bam/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.4/src/query_dsl/mod.rs:1499:15
|
1499 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `foo::models::Host: FromSqlRow<_, _>` is not satisfied
--> src/main.rs:13:38
|
13 | let results = hosts.load::<Host>(connection).expect("Error loading hosts");
| ---- ^^^^^^^^^^ the trait `FromSqlRow<_, _>` is not implemented for `foo::models::Host`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `FromSqlRow<ST, DB>`:
<(T1, T0) as FromSqlRow<(ST1, Untyped), __DB>>
<(T1, T2, T0) as FromSqlRow<(ST1, ST2, Untyped), __DB>>
<(T1, T2, T3, T0) as FromSqlRow<(ST1, ST2, ST3, Untyped), __DB>>
<(T1, T2, T3, T4, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T7, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, Untyped), __DB>>
<(T1, T2, T3, T4, T5, T6, T7, T8, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, Untyped), __DB>>
and 23 others
= note: required for `table` to implement `LoadQuery<'_, _, foo::models::Host>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/bam/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.4/src/query_dsl/mod.rs:1499:15
|
1499 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `masters-dashboard-service` due to 2 previous errors