Migrations
O Kyrux inclui um sistema de migrations baseado em arquivos .sql numerados, com rastreamento automático de quais já foram aplicadas.
Como funciona
- Arquivos
.sqlficam emdatabase/migrations/ - O nome segue o padrão
NNNN_descricao.sql(ex:0001_create_users.sql) - A tabela
kyrux_migrationsrastreia o que já foi aplicado — criada automaticamente no primeiromigrate - Cada migration é aplicada uma única vez (idempotente)
- Se a tabela já existe no banco mesmo que o arquivo tenha sido removido, apenas registra a migration sem reexecutar o SQL
Formato do arquivo de migration
Cada arquivo .sql pode conter duas seções separadas pelo marcador -- down:
-- up (implícito — tudo antes de "-- down")
CREATE TABLE IF NOT EXISTS posts (
id BIGSERIAL PRIMARY KEY,
titulo VARCHAR(200) NOT NULL DEFAULT '',
publicado BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE UNIQUE INDEX IF NOT EXISTS posts_titulo_idx ON posts (titulo);
-- down
DROP INDEX IF EXISTS posts_titulo_idx;
DROP TABLE IF EXISTS posts;
A seção up é aplicada pelo migrate. A seção down é executada pelo removemigration all para desfazer o schema com segurança antes de remover o registro.
Gerar migrations automaticamente (makemigrations)
O comando lê todos os structs com kyrux:"pk" em apps/*/models/*.go, core/security/auth/*.go e core/admin/*.go (ignorando *_test.go — fixture de teste nunca é model de verdade), compara com o schema das migrations existentes e gera o SQL com as seções up e down automaticamente:
- Tabela nova →
CREATE TABLEcompleto (+ índices unique/fk). - Campo novo em model existente →
ALTER TABLE ... ADD COLUMN(autodetectado). - Campo removido do model → a remoção não é gerada (perda de dados);
o comando avisa e escreve a sugestão
-- ALTER TABLE ... DROP COLUMN ...;comentada na migration, para você descomentar após revisar. - Renomear campo ou mudar tipo → migration manual (o detector veria um ADD + um aviso de coluna removida).
go run main.go makemigrations
Revise o arquivo gerado antes de aplicar — índices compostos, constraints e defaults personalizados devem ser ajustados manualmente.
Aplicar migrations (migrate)
go run main.go migrate
Aplica a seção up de todos os arquivos .sql ainda não registrados em kyrux_migrations. Múltiplas instruções SQL por arquivo são suportadas (separadas por ;).
Comportamento inteligente:
- Se o arquivo SQL ainda existe: executa normalmente e registra
- Se o arquivo foi removido mas a tabela existe no banco: apenas registra (evita erros de "table already exists")
- Se já foi registrada: pula (status
~)
Remover uma migration (removemigration)
# Remove apenas do disco (permite regenerar a migration)
go run main.go removemigration 0001
# Executa a seção down, remove o registro do banco e apaga o arquivo
go run main.go removemigration 0001 all
O removemigration all executa as seguintes etapas em ordem:
- Lê o arquivo e extrai a seção
-- down - Executa o SQL de reversão no banco (ex:
DROP TABLE IF EXISTS ...) - Remove o registro de
kyrux_migrations - Apaga o arquivo do disco
Se o arquivo não tiver seção
-- down, o comando aborta com uma mensagem indicando o que adicionar — nunca remove silenciosamente sem desfazer o schema.
Tipos SQL gerados
| Tipo Go | PostgreSQL | MySQL / SQLite |
|---|---|---|
string (sem size) |
TEXT |
TEXT |
string + kyrux:"size:N" |
VARCHAR(N) |
VARCHAR(N) |
int, int32 |
INTEGER |
INTEGER |
int64 |
BIGINT |
INTEGER |
float32, float64 |
DECIMAL |
DECIMAL |
bool |
BOOLEAN |
BOOLEAN |
time.Time |
TIMESTAMPTZ |
DATETIME |
campo kyrux:"pk" |
BIGSERIAL PRIMARY KEY |
INTEGER PRIMARY KEY |
campo kyrux:"unique" |
CREATE UNIQUE INDEX |
CREATE UNIQUE INDEX |
campo kyrux:"fk:tabela" |
REFERENCES tabela(id) + CREATE INDEX |
idem |
Para
fk:a tabela referenciada precisa existir antes — declare o model referenciado primeiro ou em uma migration anterior.
Campos com ponteiro (*string, *int) são gerados sem NOT NULL. Campos não-ponteiro recebem NOT NULL DEFAULT <zero>.
Migrations manuais
Para alterações que o makemigrations não cobre (ALTER TABLE, índices compostos, dados iniciais), inclua sempre a seção down:
-- database/migrations/0003_add_slug_to_posts.sql
ALTER TABLE posts ADD COLUMN IF NOT EXISTS slug VARCHAR(200) NOT NULL DEFAULT '';
CREATE UNIQUE INDEX IF NOT EXISTS posts_slug_idx ON posts (slug);
-- down
DROP INDEX IF EXISTS posts_slug_idx;
ALTER TABLE posts DROP COLUMN IF EXISTS slug;
Execute com go run main.go migrate.
Estrutura do diretório
database/
└── migrations/
├── 0001_create_users.sql ← incluída pelo framework (auth.User)
├── 0002_auto.sql ← gerada por makemigrations
└── 0003_add_slug.sql ← escrita manualmente
makemigrationsnão gera migrations de ALTER TABLE — apenas cria novas tabelas. Para mudanças em tabelas existentes, escreva a migration manualmente.