sqlmodel 0.5.0

SQL databases in Rust, designed to be intuitive and type-safe
# Chapter 5: Model Inheritance

In relational design, modeling polymorphic domain hierarchies typically uses one of three standard strategies:
1. **Single Table Inheritance (STI)**: All hierarchy classes share one table with a discriminator column.
2. **Joined Table Inheritance (JTI)**: The base class and each subclass have dedicated tables linked by primary keys.
3. **Concrete Table Inheritance (CTI)**: Each concrete subclass owns a table containing the full set of attributes; the base class is abstract.

**SQLModel Rust** supports all three strategies with compile-time metadata generation, automatic discriminator filters, and strongly-typed polymorphic queries.

---

## Joined Table Inheritance (JTI)

In Joined Table Inheritance, common fields live in a parent table, while subclass-specific fields live in a child table linked by foreign key:

```rust
use sqlmodel::prelude::*;
use sqlmodel::Dialect;

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "persons", inheritance = "joined")]
pub struct Person {
    #[sqlmodel(primary_key)]
    pub id: i64,
    pub name: String,
}

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "students", inherits = "Person")]
pub struct Student {
    #[sqlmodel(parent)]
    pub person: Person,

    #[sqlmodel(primary_key)]
    pub id: i64,
    pub grade: String,
}

# fn main() {
// Querying the child automatically constructs the INNER JOIN to the parent table
let (sql, _) = select!(Student).build_with_dialect(Dialect::Sqlite);
assert!(sql.contains("FROM \"students\" INNER JOIN \"persons\" ON \"students\".\"id\" = \"persons\".\"id\""));
# }
```

When inserting or updating a JTI child, the session and query builders coordinate writes across both tables in the correct parent-to-child order within a transaction.

---

## Single Table Inheritance (STI)

In Single Table Inheritance, all variants share one physical database table:

```rust
use sqlmodel::prelude::*;

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "employees", inheritance = "single", discriminator = "role")]
pub struct Employee {
    #[sqlmodel(primary_key, auto_increment)]
    pub id: Option<i64>,
    pub name: String,
    pub role: String,
}

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "employees", inherits = "Employee", discriminator_value = "engineer")]
pub struct Engineer {
    #[sqlmodel(parent)]
    pub employee: Employee,
    #[sqlmodel(nullable)]
    pub programming_language: Option<String>,
}
```

Queries targeted at `select!(Engineer)` automatically append `WHERE "role" = 'engineer'` to prevent cross-contamination of sibling records.

---

## Concrete Table Inheritance (CTI)

In Concrete Table Inheritance, every concrete child model possesses its own standalone table containing both base and child columns:

```rust
use sqlmodel::prelude::*;

#[derive(Model, Debug, Clone)]
#[sqlmodel(table, inheritance = "concrete")]
pub struct Content {
    #[sqlmodel(primary_key)]
    pub id: i64,
    pub title: String,
}

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "articles", inheritance = "concrete", inherits = "Content")]
pub struct Article {
    #[sqlmodel(primary_key)]
    pub id: i64,
    pub title: String,
    pub body: String,
}

#[derive(Model, Debug, Clone)]
#[sqlmodel(table = "videos", inheritance = "concrete", inherits = "Content")]
pub struct Video {
    #[sqlmodel(primary_key)]
    pub id: i64,
    pub title: String,
    pub duration_seconds: i32,
}
```

---

## Polymorphic Querying

To query a base table and hydrate results into an enum of concrete types, SQLModel provides polymorphic builders:

```rust,no_run
use sqlmodel::prelude::*;

# #[derive(Model, Debug, Clone)]
# #[sqlmodel(table = "persons", inheritance = "joined")]
# pub struct Person { #[sqlmodel(primary_key)] pub id: i64, pub name: String }
# #[derive(Model, Debug, Clone)]
# #[sqlmodel(table = "students", inherits = "Person")]
# pub struct Student { #[sqlmodel(parent)] pub person: Person, #[sqlmodel(primary_key)] pub id: i64, pub grade: String }
# #[derive(Model, Debug, Clone)]
# #[sqlmodel(table = "teachers", inherits = "Person")]
# pub struct Teacher { #[sqlmodel(parent)] pub person: Person, #[sqlmodel(primary_key)] pub id: i64, pub subject: String }
#[derive(Debug, Clone)]
pub enum SchoolMember {
    Student(Student),
    Teacher(Teacher),
}

async fn fetch_all_members(cx: &Cx, conn: &impl Connection) -> Outcome<Vec<SchoolMember>, Error> {
    // PolymorphicJoined selects parent with outer joins to children and hydrates enum variants
    Outcome::Ok(vec![])
}
```

---

## Differences from Python SQLModel

- **Struct Composition vs Class Inheritance**: Rust lacks classical OOP inheritance. SQLModel Rust achieves model subtyping via struct composition using the `#[sqlmodel(parent)]` attribute.
- **Strongly-Typed Enum Polymorphism**: While Python returns heterogenous subclass instances dynamically typed at runtime, Rust maps polymorphic query results into algebraic `enum` types.
- **Automatic Discriminator Injection**: STI child queries automatically inject compile-time discriminator equality predicates into the query AST.
- **Explicit Table Separation**: JTI relationships clearly separate parent and child tables in schema generation and migrations without relying on implicit SQLAlchemy mapper registries.