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
317 lines
8.0 KiB
Markdown
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
|