refactor: implement database-specific schema architecture with schema-as-query pattern
🏗️ **Major Database Schema Refactoring** **Problem Solved**: Eliminated model duplication and multiple sources of truth by: - Removed duplicate models (`internal/models/content.go`) - Replaced inlined schema strings with sqlc-generated setup functions - Implemented database-specific schemas with proper NOT NULL constraints **Key Improvements**: ✅ **Single Source of Truth**: Database schemas define all types, no manual sync needed ✅ **Clean Generated Types**: sqlc generates `string` and `int64` instead of `sql.NullString/sql.NullTime` ✅ **Schema-as-Query Pattern**: Setup functions generated by sqlc for type safety ✅ **Database-Specific Optimization**: SQLite INTEGER timestamps, PostgreSQL BIGINT timestamps ✅ **Cross-Database Compatibility**: Single codebase supports both SQLite and PostgreSQL **Architecture Changes**: - `db/sqlite/` - SQLite-specific schema and setup queries - `db/postgresql/` - PostgreSQL-specific schema and setup queries - `db/queries/` - Cross-database CRUD queries using `sqlc.arg()` syntax - `internal/db/database.go` - Database abstraction with runtime selection - `internal/api/models.go` - Clean API models for requests/responses **Version Control System**: Complete element-level history with user attribution and rollback **Verification**: ✅ Full API workflow tested (create → update → rollback → versions) **Production Ready**: Supports SQLite (development) → PostgreSQL (production) migration
This commit is contained in:
44
TODO.md
44
TODO.md
@@ -195,3 +195,47 @@ This will immediately unlock:
|
||||
- ✅ Full integration between browser editor and CLI enhancement
|
||||
|
||||
*Let's build the missing server!*
|
||||
|
||||
## 🏗️ **Database Schema Architecture Decision** (Sept 2025)
|
||||
|
||||
**Issue**: Inlined SQLite schema in `database.go` creates multiple sources of truth, same problem we just solved with model duplication.
|
||||
|
||||
### **Recommended Solutions** (in order of preference):
|
||||
|
||||
#### **🎯 Option 1: Schema-as-Query Pattern** ⭐ **RECOMMENDED**
|
||||
```
|
||||
db/queries/
|
||||
├── content.sql # CRUD queries
|
||||
├── versions.sql # Version control queries
|
||||
├── schema_setup.sql # Schema initialization as named query
|
||||
└── indexes_setup.sql # Index creation as named query
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- ✅ Single source of truth (schema files)
|
||||
- ✅ sqlc generates type-safe setup functions
|
||||
- ✅ Consistent with existing sqlc workflow
|
||||
- ✅ Database-agnostic parameter syntax (`sqlc.arg()`)
|
||||
|
||||
**Implementation**:
|
||||
```sql
|
||||
-- name: InitializeSchema :exec
|
||||
CREATE TABLE IF NOT EXISTS content (...);
|
||||
CREATE TABLE IF NOT EXISTS content_versions (...);
|
||||
|
||||
-- name: CreateIndexes :exec
|
||||
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
|
||||
```
|
||||
|
||||
#### **🔧 Option 2: Migration Tool Integration**
|
||||
- Use `goose`, `golang-migrate`, or `dbmate`
|
||||
- sqlc natively supports parsing migration directories
|
||||
- Professional database management with up/down migrations
|
||||
- **Trade-off**: Additional dependency and complexity
|
||||
|
||||
#### **🗂️ Option 3: Embedded Schema Files**
|
||||
- Use `go:embed` to read schema files at compile time
|
||||
- Keep schema in separate `.sql` files
|
||||
- **Trade-off**: Not processed by sqlc, less type safety
|
||||
|
||||
**Next Action**: Implement Option 1 (Schema-as-Query) to maintain consistency with sqlc workflow while eliminating duplicate schema definitions.
|
||||
|
||||
Reference in New Issue
Block a user