Skip to content

feat!: Expose on_delete and on_update fields for ForeignKey field#576

Draft
ElijahAhianyo wants to merge 1 commit into
masterfrom
elijah/fk-on-delete-on-update
Draft

feat!: Expose on_delete and on_update fields for ForeignKey field#576
ElijahAhianyo wants to merge 1 commit into
masterfrom
elijah/fk-on-delete-on-update

Conversation

@ElijahAhianyo
Copy link
Copy Markdown
Contributor

@ElijahAhianyo ElijahAhianyo commented May 19, 2026

Related issue or discussion

Fixes #540

Description

The code example below:

#[model]
#[derive(Debug, Clone)]
pub struct Customer {
    #[model(primary_key)]
    id: Auto<i64>,
}

#[model]
#[derive(Debug, Clone)]
pub struct Product {
    #[model(primary_key)]
    id: Auto<i64>,
}

#[model]
#[derive(Debug, Clone)]
pub struct Order {
    #[model(primary_key)]
    id: Auto<i64>,
    #[model(foreign_key(on_delete = "cascade"))]
    customer: ForeignKey<Customer>,
    #[model(foreign_key(on_delete = "cascade", on_update = "set_none"))]
    product: Option<ForeignKey<Product>>,
}

Generates the migration file below:

#[derive(Debug, Copy, Clone)]
pub(super) struct Migration;
impl ::cot::db::migrations::Migration for Migration {
    const APP_NAME: &'static str = "playground";
    const MIGRATION_NAME: &'static str = "m_0002_auto_20260519_011613";
    const DEPENDENCIES: &'static [::cot::db::migrations::MigrationDependency] = &[
        ::cot::db::migrations::MigrationDependency::migration("playground", "m_0001_initial"),
    ];
    const OPERATIONS: &'static [::cot::db::migrations::Operation] = &[
        ::cot::db::migrations::Operation::create_model()
            .table_name(::cot::db::Identifier::new("playground__product"))
            .fields(
                &[
                    ::cot::db::migrations::Field::new(
                            ::cot::db::Identifier::new("id"),
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
                        )
                        .set_null(
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
                        )
                        .auto()
                        .primary_key(),
                ],
            )
            .build(),
        ::cot::db::migrations::Operation::create_model()
            .table_name(::cot::db::Identifier::new("playground__customer"))
            .fields(
                &[
                    ::cot::db::migrations::Field::new(
                            ::cot::db::Identifier::new("id"),
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
                        )
                        .set_null(
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
                        )
                        .auto()
                        .primary_key(),
                ],
            )
            .build(),
        ::cot::db::migrations::Operation::create_model()
            .table_name(::cot::db::Identifier::new("playground__order"))
            .fields(
                &[
                    ::cot::db::migrations::Field::new(
                            ::cot::db::Identifier::new("id"),
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
                        )
                        .set_null(
                            <cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
                        )
                        .auto()
                        .primary_key(),
                    ::cot::db::migrations::Field::new(
                            ::cot::db::Identifier::new("customer"),
                            <cot::db::ForeignKey<
                                crate::Customer,
                            > as ::cot::db::DatabaseField>::TYPE,
                        )
                        .set_null(
                            <cot::db::ForeignKey<
                                crate::Customer,
                            > as ::cot::db::DatabaseField>::NULLABLE,
                        )
                        .foreign_key(
                            <crate::Customer as ::cot::db::Model>::TABLE_NAME,
                            <crate::Customer as ::cot::db::Model>::PRIMARY_KEY_NAME,
                            ::cot::db::ForeignKeyOnDeletePolicy::Cascade,
                            ::cot::db::ForeignKeyOnUpdatePolicy::Cascade,
                        ),
                    ::cot::db::migrations::Field::new(
                            ::cot::db::Identifier::new("product"),
                            <Option<
                                cot::db::ForeignKey<crate::Product>,
                            > as ::cot::db::DatabaseField>::TYPE,
                        )
                        .set_null(
                            <Option<
                                cot::db::ForeignKey<crate::Product>,
                            > as ::cot::db::DatabaseField>::NULLABLE,
                        )
                        .foreign_key(
                            <crate::Product as ::cot::db::Model>::TABLE_NAME,
                            <crate::Product as ::cot::db::Model>::PRIMARY_KEY_NAME,
                            ::cot::db::ForeignKeyOnDeletePolicy::Cascade,
                            ::cot::db::ForeignKeyOnUpdatePolicy::SetNone,
                        ),
                ],
            )
            .build(),
    ];
}

#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Customer {
    #[model(primary_key)]
    id: cot::db::Auto<i64>,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Order {
    #[model(primary_key)]
    id: cot::db::Auto<i64>,
    #[model(foreign_key(on_delete = "cascade"))]
    customer: cot::db::ForeignKey<crate::Customer>,
    #[model(foreign_key(on_delete = "cascade", on_update = "set_none"))]
    product: Option<cot::db::ForeignKey<crate::Product>>,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Product {
    #[model(primary_key)]
    id: cot::db::Auto<i64>,
}

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Refactor / cleanup
  • Performance improvement
  • Other (describe above)

@github-actions github-actions Bot added C-cli Crate: cot-cli (issues and Pull Requests related to Cot CLI) C-codegen Crate: cot-codegen labels May 19, 2026
@ElijahAhianyo ElijahAhianyo marked this pull request as ready for review May 19, 2026 01:07
@ElijahAhianyo ElijahAhianyo marked this pull request as draft May 19, 2026 01:08
@ElijahAhianyo ElijahAhianyo changed the title Expose on_delete and on_update fields for ForeignKey field feat!: Expose on_delete and on_update fields for ForeignKey field May 19, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 19, 2026

🐰 Bencher Report

Branchelijah/fk-on-delete-on-update
Testbedgithub-ubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
empty_router/empty_router📈 view plot
🚷 view threshold
5,733.10 µs
(-5.91%)Baseline: 6,093.20 µs
7,677.76 µs
(74.67%)
json_api/json_api📈 view plot
🚷 view threshold
987.16 µs
(-8.12%)Baseline: 1,074.37 µs
1,323.65 µs
(74.58%)
nested_routers/nested_routers📈 view plot
🚷 view threshold
928.99 µs
(-6.38%)Baseline: 992.35 µs
1,204.08 µs
(77.15%)
single_root_route/single_root_route📈 view plot
🚷 view threshold
897.38 µs
(-6.02%)Baseline: 954.82 µs
1,167.50 µs
(76.86%)
single_root_route_burst/single_root_route_burst📈 view plot
🚷 view threshold
16,985.00 µs
(-4.17%)Baseline: 17,724.56 µs
21,190.21 µs
(80.15%)
🐰 View full continuous benchmarking report in Bencher

@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cot-codegen/src/model.rs 75.00% 10 Missing and 2 partials ⚠️
Flag Coverage Δ
rust 90.28% <81.81%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cot-cli/src/migration_generator.rs 89.21% <100.00%> (+0.11%) ⬆️
cot-codegen/src/model.rs 92.15% <75.00%> (-2.54%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-cli Crate: cot-cli (issues and Pull Requests related to Cot CLI) C-codegen Crate: cot-codegen

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose on_delete and on_update for ForeignKey fields

1 participant