I'm trying to find a way of leveraging Rusts type system to handle database foreign keys.
Suppose I have these tables (simplified Sqlite):
create table order (
id number primary key,
customer text
)
create table item (
id number primary key,
description text,
order_id number
)
Within my application, I would like to have separate types for the IDs and use those types to implement overloaded functions in the impl of my database struct, such that Rust knows that db.get(item.order_id) is of type Order while db.get(ItemId::from(1)) or something like that would return an Item.
What doesn't work is a type parameter on a primitive type, although this would look very natural but of course neither the type definitions nor the duplicate function definitions would fly:
type Id<Item> = u32;
type Id<Order> = u32;
impl Database {
fn get<Item>(&self, id: Id<Item>) -> Item {...}
fn get<Order>(&self, id: Id<Order>) -> Order {...}
}
Replacing Id<Item> with ItemId doesn't make it much better.
I have experimented with structs and traits which kind of works, but still looks pretty ugly.
Is there an idiomatic way of doing this?
Cheers,
Hans-Martin