Rust Code Generator
A proof-of-concept Rust code generator using Go text templates. This demonstrates how to add multi-language support to db-catalyst.
Overview
This package generates Rust structs and query functions from SQL schemas using:
- Go text templates for code generation
- Semantic type system for language-agnostic type mapping
- sqlx as the target database library
Architecture
SQL Schema → Semantic Types → Rust Mapper → Templates → Rust Code
↓
INTEGER → CategoryBigInteger → i64
TEXT → CategoryText → String
BOOLEAN → CategoryBoolean → bool
Generated Code Example
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT,
created_at INTEGER NOT NULL
);
Output (Rust)
// Code generated by db-catalyst. DO NOT EDIT.
#[derive(Debug, Clone, sqlx::FromRow)]
pub struct Users {
pub id: i64,
pub name: String,
pub email: Option<String>,
pub created_at: i64,
}
pub type UsersId = i64;
pub type UsersRef = Users;
Type Mappings
| SQLite Type |
Rust Type |
Nullable |
| INTEGER |
i64 |
Option |
| TEXT |
String |
Option |
| BOOLEAN |
bool |
Option |
| REAL |
f64 |
Option |
| BLOB |
Vec |
Option<Vec> |
| TIMESTAMP |
chrono::DateTimechrono::Utc |
Option<...> |
| UUID |
uuid::Uuid |
Optionuuid::Uuid |
| JSON |
serde_json::Value |
Option<...> |
Usage
import "github.com/electwix/db-catalyst/internal/codegen/rust"
// Create generator
gen, err := rust.NewGenerator()
if err != nil {
log.Fatal(err)
}
// Generate from tables
files, err := gen.GenerateModels(tables)
if err != nil {
log.Fatal(err)
}
// Write files
for _, file := range files {
err := os.WriteFile(file.Path, file.Content, 0644)
if err != nil {
log.Fatal(err)
}
}
Templates
Templates are embedded using Go 1.16+ embed package:
templates/model.tmpl - Struct definitions
templates/queries.tmpl - Query functions
Template Functions
snakeCase - Convert to snake_case
pascalCase - Convert to PascalCase
rustType - Convert semantic type to Rust type
Future Enhancements
- Query Generation: Generate sqlx query! macros
- Migrations: Generate Diesel migration files
- Async Traits: Support for async database traits
- Custom Types: User-defined type mappings
- Documentation: Generate rustdoc comments
Design Decisions
Why Templates?
- Pros:
- Easy to read/write Rust syntax directly
- Fast iteration
- Language-native formatting
- Cons:
- No compile-time safety
- Runtime errors possible
Why sqlx?
- Compile-time SQL verification
- Async/await support
- Most popular Rust SQL library
- Good ergonomics
Alternative Approaches
- String Builder: Simpler but harder to maintain
- Rust AST: Would need Rust parser in Go (complex)
- External Tool: Call
rustfmt or similar (slower)
Comparison with Go Generator
| Aspect |
Go |
Rust |
| Method |
go/ast AST |
text/template |
| Type Safety |
Compile-time |
Runtime |
| Formatting |
goimports |
rustfmt (manual) |
| Complexity |
Higher |
Lower |
| Maintenance |
Harder |
Easier |
The Go AST approach is better for Go due to excellent tooling. Templates are better for other languages where we don't have Go-native AST libraries.
Testing
Run tests:
go test ./internal/codegen/rust -v
The tests verify:
- Template loading and execution
- Type mappings (SQLite → Rust)
- Naming conventions (snake_case, PascalCase)
- File generation
- Module structure
Integration
To integrate with main db-catalyst:
- Add language selection to config
- Create LanguageGenerator interface
- Route to appropriate generator (Go/Rust/TypeScript)
- Generate all files for selected languages
See docs/language-agnostic-refactor.md for full architecture.