Skip to content

Commit 11406d6

Browse files
authored
Merge pull request #126 from dev-five-git/fk-new-option
Add rm fk required column option
2 parents 228adba + 002ea1e commit 11406d6

19 files changed

Lines changed: 1109 additions & 203 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"changes":{"crates/vespertide-core/Cargo.toml":"Patch","crates/vespertide-loader/Cargo.toml":"Patch","crates/vespertide-query/Cargo.toml":"Patch","crates/vespertide-naming/Cargo.toml":"Patch","crates/vespertide-exporter/Cargo.toml":"Patch","crates/vespertide-planner/Cargo.toml":"Patch","crates/vespertide/Cargo.toml":"Patch","crates/vespertide-macro/Cargo.toml":"Patch","crates/vespertide-config/Cargo.toml":"Patch","crates/vespertide-cli/Cargo.toml":"Patch"},"note":"Add rm fk required column option","date":"2026-03-30T05:55:13.437604900Z"}

CLAUDE.md

Lines changed: 1 addition & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1 @@
1-
# CLAUDE.md
2-
3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4-
5-
## Overview
6-
7-
Vespertide is a Rust workspace for defining database schemas in JSON/YAML and generating migration plans and SQL from model diffs. It enables declarative schema management by comparing the current model state against a baseline reconstructed from applied migrations.
8-
9-
The workspace uses Rust **edition 2024**.
10-
11-
## Build and Test Commands
12-
13-
```bash
14-
# Build the entire workspace
15-
cargo build
16-
17-
# Run all tests
18-
cargo test
19-
20-
# Run tests for a specific crate
21-
cargo test -p vespertide-core
22-
cargo test -p vespertide-planner
23-
24-
# Run a single test
25-
cargo test -p vespertide-planner test_name
26-
27-
# Run tests with output shown
28-
cargo test -- --nocapture
29-
30-
# Format code
31-
cargo fmt
32-
33-
# Lint (important: use all targets and features)
34-
cargo clippy --all-targets --all-features
35-
36-
# Regenerate JSON schemas
37-
cargo run -p vespertide-schema-gen -- --out schemas
38-
39-
# Snapshot testing (exporter crate)
40-
cargo insta test -p vespertide-exporter
41-
cargo insta accept
42-
43-
# Run CLI commands (use -p vespertide-cli)
44-
cargo run -p vespertide-cli -- init
45-
cargo run -p vespertide-cli -- new user
46-
cargo run -p vespertide-cli -- diff
47-
cargo run -p vespertide-cli -- sql
48-
cargo run -p vespertide-cli -- revision -m "message"
49-
cargo run -p vespertide-cli -- status
50-
cargo run -p vespertide-cli -- log
51-
cargo run -p vespertide-cli -- export --orm seaorm
52-
```
53-
54-
## Architecture
55-
56-
### Core Data Flow
57-
58-
1. **Schema Definition**: Users define tables in JSON files (`TableDef`) in the `models/` directory
59-
2. **Baseline Reconstruction**: Applied migrations are replayed to rebuild the baseline schema
60-
3. **Diffing**: Current models are compared against the baseline to compute changes
61-
4. **Planning**: Changes are converted into a `MigrationPlan` with versioned actions
62-
5. **SQL Generation**: Migration actions are translated into SQL statements
63-
64-
### Crate Responsibilities
65-
66-
- **vespertide-core**: Data structures (`TableDef`, `ColumnDef`, `ColumnType`, `MigrationAction`, `MigrationPlan`, constraints, indexes)
67-
- `ColumnType` enum with `Simple(SimpleColumnType)` and `Complex(ComplexColumnType)` variants
68-
- `ColumnType::to_sql()` and `ColumnType::to_rust_type()` methods for type conversion
69-
- **vespertide-planner**:
70-
- `schema_from_plans()`: Replays applied migrations to reconstruct baseline schema
71-
- `diff_schemas()`: Compares two schemas and generates migration actions
72-
- `plan_next_migration()`: Combines baseline reconstruction + diffing to create the next migration
73-
- `apply_action()`: Applies a single migration action to a schema (used during replay)
74-
- `validate_*()`: Validates schemas and migration plans
75-
- **vespertide-query**: Converts `MigrationAction` → SQL with bind parameters
76-
- Uses `ColumnType::to_sql()` method for SQL type conversion
77-
- **vespertide-config**: Manages `vespertide.json` (models/migrations directories, naming case preferences)
78-
- **vespertide-cli**: Command-line interface implementation
79-
- **vespertide-exporter**: Exports schemas to other formats (e.g., SeaORM entities)
80-
- Uses `ColumnType::to_rust_type(nullable)` method for Rust type conversion
81-
- **vespertide-schema-gen**: Generates JSON Schema files for validation
82-
- **vespertide-loader**: Loads migrations and models from filesystem (JSON/YAML)
83-
- **vespertide-naming**: Naming conventions and case conversion helpers
84-
- **vespertide-macro**: Compile-time migration macro (`vespertide_migration!`) for SeaORM
85-
- **vespertide**: Main crate that re-exports vespertide-core and vespertide-macro
86-
87-
### Key Architectural Patterns
88-
89-
**Migration Replay Pattern**: The planner doesn't store a "current database state" - it reconstructs it by replaying all applied migrations in order. This ensures the baseline is always derivable from the migration history.
90-
91-
**Declarative Diffing**: Users declare the desired end state in model files. The diff engine compares this against the reconstructed baseline to compute necessary changes.
92-
93-
**Action-Based Migrations**: All changes are expressed as typed `MigrationAction` enums (CreateTable, AddColumn, ModifyColumnType, etc.) rather than raw SQL. SQL generation happens in a separate layer.
94-
95-
## Important Implementation Details
96-
97-
### ColumnDef Structure
98-
When creating `ColumnDef` instances in tests or code, you must initialize ALL fields including the newer inline constraint fields:
99-
100-
```rust
101-
ColumnDef {
102-
name: "id".into(),
103-
r#type: ColumnType::Simple(SimpleColumnType::Integer),
104-
nullable: false,
105-
default: None,
106-
comment: None,
107-
primary_key: None, // Inline PK declaration
108-
unique: None, // Inline unique constraint
109-
index: None, // Inline index creation
110-
foreign_key: None, // Inline FK definition
111-
}
112-
```
113-
114-
These inline fields (added recently) allow constraints to be defined directly on columns in addition to table-level `TableConstraint` definitions.
115-
116-
### ColumnType Structure
117-
`ColumnType` is an enum with two variants:
118-
- `Simple(SimpleColumnType)`: Built-in types like `Integer`, `Text`, `Boolean`, etc.
119-
- `Complex(ComplexColumnType)`: Types with parameters like `Varchar { length }` or `Custom { custom_type }`
120-
121-
**Important**: In Rust code, always use `ColumnType::Simple(SimpleColumnType::Integer)` instead of the old `ColumnType::Integer` syntax. The `From` trait is implemented for convenience:
122-
```rust
123-
// These are equivalent:
124-
ColumnType::Simple(SimpleColumnType::Integer)
125-
SimpleColumnType::Integer.into()
126-
```
127-
128-
### ColumnType Methods
129-
`ColumnType` provides two utility methods:
130-
- `to_sql()`: Returns the SQL type string (e.g., `"INTEGER"`, `"VARCHAR(255)"`)
131-
- `to_rust_type(nullable: bool)`: Returns the Rust type string for SeaORM entity generation (e.g., `"i32"` or `"Option<i32>"`)
132-
133-
These methods replace the old standalone functions `column_type_sql()` and `rust_type()`.
134-
135-
### Foreign Key Definition
136-
Foreign keys can be defined inline on columns via the `foreign_key` field:
137-
138-
```rust
139-
pub struct ForeignKeyDef {
140-
pub ref_table: TableName,
141-
pub ref_columns: Vec<ColumnName>,
142-
pub on_delete: Option<ReferenceAction>,
143-
pub on_update: Option<ReferenceAction>,
144-
}
145-
```
146-
147-
### Migration Plan Validation
148-
- Non-nullable columns added to existing tables require either a `default` value or a `fill_with` backfill expression
149-
- Schemas are validated for constraint consistency before diffing
150-
- The planner validates that column/table names follow the configured naming case
151-
152-
### SQL Generation Target
153-
SQL generation currently uses PostgreSQL-compatible syntax. The query builder can be extended to support other database systems.
154-
155-
### JSON Schema Generation
156-
The `vespertide-schema-gen` crate uses `schemars` to generate JSON Schemas from the Rust types. After modifying core data structures, regenerate schemas with:
157-
```bash
158-
cargo run -p vespertide-schema-gen -- --out schemas
159-
```
160-
161-
Schema base URL can be overridden via `VESP_SCHEMA_BASE_URL` environment variable.
162-
163-
## Testing Patterns
164-
165-
- Tests use helper functions like `col()` and `table()` to reduce boilerplate
166-
- Use `rstest` for parameterized tests (common in planner/query crates)
167-
- Use `serial_test::serial` for tests that modify the filesystem or working directory
168-
- Snapshot testing with `insta` is used in the exporter crate
169-
170-
## Limitations
171-
172-
- YAML loading is not implemented (templates can be generated but not parsed)
1+
@AGENTS.md

crates/vespertide-cli/CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@AGENTS.md

crates/vespertide-cli/src/commands/diff.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ mod tests {
462462
column: "email".into(),
463463
nullable: false,
464464
fill_with: None,
465+
delete_null_rows: None,
465466
},
466467
format!(
467468
"{} {}.{} {} {}",
@@ -478,6 +479,7 @@ mod tests {
478479
column: "email".into(),
479480
nullable: true,
480481
fill_with: None,
482+
delete_null_rows: None,
481483
},
482484
format!(
483485
"{} {}.{} {} {}",

0 commit comments

Comments
 (0)