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:
2025-09-09 00:25:07 +02:00
parent 161c320304
commit bab329b429
41 changed files with 3703 additions and 561 deletions

44
TODO.md
View File

@@ -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.