ids.alfacom.it/database-schema/README.md
marco370 7b85fcc020 Implement a database versioning system to speed up updates
Add a database versioning system that tracks applied migrations and only runs new ones, significantly improving update speed.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ab56b852-52de-4cd1-a489-5cf48f3a2965
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/myJmPIa
2025-11-22 07:51:56 +00:00

317 lines
8.0 KiB
Markdown

# Database Schema & Migrations - Sistema Versionato
## Overview
Sistema intelligente di migrazioni database con **version tracking**. Applica solo le migrazioni necessarie, velocizzando gli aggiornamenti.
## 🎯 Vantaggi
**Veloce**: Applica solo migrazioni mancanti (non riesegue quelle già fatte)
**Sicuro**: Traccia versione database, previene errori
**Automatico**: Integrato in `update_from_git.sh`
**Idempotente**: Puoi eseguire più volte senza problemi
## 📋 Come Funziona
### 1. Tabella `schema_version`
Traccia la versione corrente del database:
```sql
CREATE TABLE schema_version (
id INTEGER PRIMARY KEY DEFAULT 1, -- Sempre 1 (solo 1 riga)
version INTEGER NOT NULL, -- Versione corrente (es: 5)
applied_at TIMESTAMP, -- Quando è stata applicata
description TEXT -- Descrizione ultima migrazione
);
```
### 2. Migrazioni Numerate
Ogni migrazione SQL ha un numero sequenziale nel nome:
```
database-schema/migrations/
├── 000_init_schema_version.sql ← Inizializza tracking (sempre eseguita)
├── 001_add_missing_columns.sql ← Migrazione 1
├── 002_add_indexes.sql ← Migrazione 2
├── 003_alter_detections.sql ← Migrazione 3
└── ...
```
**Convenzione nome**: `XXX_description.sql` dove XXX è numero a 3 cifre (001, 002, 010, 100, etc.)
### 3. Logica Applicazione
```bash
# Script legge versione corrente
CURRENT_VERSION = SELECT version FROM schema_version WHERE id = 1;
# Esempio: 2
# Trova migrazioni con numero > 2
Trova: 003_*.sql, 004_*.sql, 005_*.sql
# Applica in ordine
Per ogni migrazione:
1. Esegui SQL
2. Aggiorna versione: UPDATE schema_version SET version = 3
3. Prossima migrazione...
# Risultato: Database aggiornato da v2 a v5
```
## 🚀 Uso Quotidiano
### Aggiornamento Automatico (Consigliato)
```bash
# Sul server AlmaLinux
cd /opt/ids
sudo ./deployment/update_from_git.sh
# Lo script esegue automaticamente:
# 1. Git pull
# 2. npm install
# 3. pip install
# 4. ./database-schema/apply_migrations.sh ← Applica migrazioni
# 5. npm run db:push ← Sincronizza schema Drizzle
# 6. Restart servizi
```
**Output atteso**:
```
🗄️ Sistema Migrazioni Database (Versioned)
📋 Verifica sistema versioning...
✅ Sistema versioning attivo
📊 Versione database corrente: 2
📋 Trovate 3 migrazioni da applicare
🔄 Applicando migrazione 3: 003_add_indexes.sql
✅ Migrazione 3 applicata con successo
🔄 Applicando migrazione 4: 004_alter_table.sql
✅ Migrazione 4 applicata con successo
🔄 Applicando migrazione 5: 005_new_feature.sql
✅ Migrazione 5 applicata con successo
╔═══════════════════════════════════════════════╗
║ ✅ MIGRAZIONI COMPLETATE ║
╚═══════════════════════════════════════════════╝
📊 Versione database: 2 → 5
```
Se database già aggiornato:
```
📊 Versione database corrente: 5
✅ Database già aggiornato (nessuna migrazione da applicare)
```
### Applicazione Manuale
```bash
cd /opt/ids/database-schema
./apply_migrations.sh
```
### Verifica Versione Corrente
```bash
psql $DATABASE_URL -c "SELECT * FROM schema_version;"
id | version | applied_at | description
----+---------+----------------------------+-----------------------
1 | 5 | 2025-11-22 14:30:15.123456 | Migration 5: Add indexes
```
## 🔨 Creare Nuova Migrazione
### STEP 1: Determina Prossimo Numero
```bash
# Trova ultima migrazione
ls database-schema/migrations/ | grep "^[0-9]" | sort | tail -n 1
# Output: 005_add_indexes.sql
# Prossima migrazione: 006
```
### STEP 2: Crea File Migrazione
```bash
# Formato: XXX_description.sql
touch database-schema/migrations/006_add_new_table.sql
```
### STEP 3: Scrivi SQL
```sql
-- ============================================================================
-- Migration 006: Add new table for feature X
-- ============================================================================
-- Descrizione: Crea tabella per gestire feature X
-- Data: 2025-11-22
-- ============================================================================
CREATE TABLE IF NOT EXISTS my_new_table (
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
-- Crea indici
CREATE INDEX IF NOT EXISTS my_new_table_name_idx ON my_new_table(name);
-- Inserisci dati iniziali (se necessario)
INSERT INTO my_new_table (name)
SELECT 'Default Entry'
WHERE NOT EXISTS (SELECT 1 FROM my_new_table LIMIT 1);
```
**Best Practices**:
- Usa sempre `IF NOT EXISTS` (idempotenza)
- Usa `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`
- Documenta bene la migrazione
- Testa localmente prima di committare
### STEP 4: Testa Localmente (Replit)
```bash
# Su Replit
cd database-schema
./apply_migrations.sh
# Verifica versione aggiornata
psql $DATABASE_URL -c "SELECT version FROM schema_version;"
```
### STEP 5: Commit & Deploy
```bash
# Su Replit
./push-gitlab.sh
# Sul server
cd /opt/ids
sudo ./deployment/update_from_git.sh
```
## 📊 Esempi Migrazioni Comuni
### Aggiungere Colonna
```sql
-- Migration XXX: Add email column to users
ALTER TABLE users
ADD COLUMN IF NOT EXISTS email TEXT;
```
### Creare Indice
```sql
-- Migration XXX: Add index on source_ip
CREATE INDEX IF NOT EXISTS network_logs_source_ip_idx
ON network_logs(source_ip);
```
### Modificare Tipo Colonna (ATTENZIONE!)
```sql
-- Migration XXX: Change column type
-- NOTA: Può causare perdita dati se incompatibile!
ALTER TABLE detections
ALTER COLUMN risk_score TYPE DECIMAL(5,2)
USING risk_score::DECIMAL(5,2);
```
### Inserire Dati Iniziali
```sql
-- Migration XXX: Add default admin user
INSERT INTO users (username, role)
SELECT 'admin', 'admin'
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE username = 'admin'
);
```
## 🔍 Troubleshooting
### Errore: Migrazione Fallisce
```bash
# Verifica errore
psql $DATABASE_URL -c "SELECT version FROM schema_version;"
# Se migrazione 5 è fallita, il database è ancora a v4
# Fix: Correggi file 005_*.sql e riesegui
./apply_migrations.sh
```
### Reset Completo (ATTENZIONE!)
```bash
# ⚠️ DISTRUTTIVO - Cancella tutti i dati!
psql $DATABASE_URL << 'EOF'
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO ids_user;
GRANT ALL ON SCHEMA public TO public;
EOF
# Ricrea schema da zero
npm run db:push --force
./apply_migrations.sh
```
### Saltare Migrazione (Avanzato)
```bash
# Se migrazione 003 è già applicata manualmente
# Aggiorna versione manualmente
psql $DATABASE_URL -c "
UPDATE schema_version
SET version = 3,
description = 'Migration 3: Manually applied',
applied_at = NOW()
WHERE id = 1;
"
```
## 🎯 Workflow Completo
### Sviluppo (Replit)
1. Modifica schema in `shared/schema.ts`
2. Esegui `npm run db:push` (sincronizza Drizzle)
3. Se serve migrazione SQL custom:
- Crea `XXX_description.sql`
- Testa con `./apply_migrations.sh`
4. Commit: `./push-gitlab.sh`
### Produzione (AlmaLinux)
1. `sudo ./deployment/update_from_git.sh`
2. Script applica automaticamente migrazioni
3. Verifica: `psql $DATABASE_URL -c "SELECT * FROM schema_version;"`
## 📝 Note Tecniche
- **000_init_schema_version.sql**: Sempre eseguita (idempotente), inizializza tracking
- **Constraint**: Tabella `schema_version` ammette solo 1 riga (id=1)
- **Formato numeri**: Usa 3 cifre (001, 002, ..., 010, ..., 100) per ordinamento corretto
- **Drizzle vs SQL**: `npm run db:push` sincronizza schema TypeScript, migrazioni SQL sono per logica custom
## ✅ Checklist Pre-Commit
Quando crei nuova migrazione:
- [ ] Numero sequenziale corretto (XXX+1)
- [ ] Nome file descrittivo
- [ ] Commento header con descrizione
- [ ] SQL idempotente (`IF NOT EXISTS`, etc.)
- [ ] Testata localmente su Replit
- [ ] Versione aggiornata: `SELECT version FROM schema_version;`
- [ ] Commit message chiaro