Revisão de Código para SQL
Evidências de EXPLAIN e notas de rollback são necessárias para pull requests de PostgreSQL 18.4 - checklist do revisor para migrações, queries ORM e SQL ad hoc em repositórios de aplicação.
Receita
## Checklist de Revisão de PR SQL (copiar no comentário da revisão)
### Migrações
- [ ] Versão única; nome do arquivo tem ID do ticket
- [ ] Risco de lock: baixo / médio / alto (Skill de Segurança de Migração)
- [ ] CONCURRENTLY para índice de produção em tabelas grandes
- [ ] SQL de Rollback em db/rollback/ ou corpo do PR
- [ ] Ordem de deploy: migração antes da aplicação
### Queries
- [ ] EXPLAIN (ANALYZE, BUFFERS) de staging anexado
- [ ] Sem regressão de seq scan em tabelas grandes
- [ ] Queries parametrizadas ($1 / binds nomeados)
- [ ] LIMIT em endpoints de lista
### Segurança
- [ ] Privilégio mínimo da role (não superusuário)
- [ ] search_path definido ou nomes com schema qualificado
- [ ] Políticas RLS se tabela de tenantQuando usar isso:
- Todo PR que toca em
db/migrations/,*.sql, arquivos de query do repositório - SQL gerado por alterações de Prisma, SQLAlchemy, Django ORM
- SQL de Analytics juntando tabelas PII
Exemplo de Trabalho
PR: Adicionar método de repositório findOpenOrdersByTenant.
Autor fornece:
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, total, created_at
FROM orders
WHERE tenant_id = $1 AND status = 'open'
ORDER BY created_at DESC
LIMIT 100;Index Scan using idx_orders_tenant_status on orders
Buffers: shared hit=120 read=4
Execution Time: 1.2 msRevisor aprova - índice existe, LIMIT presente, buffers razoáveis.
Exemplo de PR ruim (rejeitar):
SELECT * FROM orders WHERE tenant_id = $1 OR tenant_id = $2;
-- Sem EXPLAIN, sem LIMIT, OR impede índice em alguns planejadoresModelo de comentário do revisor:
Solicitar alterações:
1. Anexar EXPLAIN (ANALYZE, BUFFERS) de staging
2. Substituir OR por padrão IN (...) ou UNION ALL
3. Listar colunas explicitamente; remover SELECT *
4. Ver Skill de Revisão EXPLAIN para rubrica de aprovação/falhaMergulho Profundo
Tabela de Revisão de Migração
| Sinal | Aprovar | Solicitar alterações |
|---|---|---|
CREATE INDEX em tabela grande | CONCURRENTLY em arquivo separado | Índice em transação única |
NOT NULL nova coluna | expand-contract ou caminho rápido de default do PG documentado | Risco de reescrita de tabela não explicado |
| Adicionar FK | NOT VALID + VALIDATE dividido | Validação inline em tabela enorme |
| Backfill de dados | UPDATE em batch com commit | Uma transação enorme |
Específico de ORM
# RUIM: N+1
for order in orders:
items = session.query(Item).filter_by(order_id=order.id).all()
# BOM: evidência de joinedload no PR
orders = session.query(Order).options(joinedload(Order.items)).filter(...)- Exigir contagem de queries ou snippet de log SQL para alterações em caminhos críticos
Notas de Rollback
-- rollback/V20260709_128__orders_priority_down.sql
DROP INDEX CONCURRENTLY IF EXISTS idx_orders_priority;
ALTER TABLE orders DROP COLUMN IF EXISTS priority;- Mesmo equipes "forward-only" armazenam rollback para uso em incidentes
Armadilhas
- Aprovar sem executar EXPLAIN - confie, mas verifique no clone de staging. Correção: revisor verifica semanalmente.
- Migração apenas no PR da aplicação - ausente do repositório da plataforma. Correção: caminho de fonte única em CONTRIBUTING.
- Funções definidoras de segurança sem search_path - escalonamento de privilégios. Correção:
SET search_path = pg_catalog, app. - Conceder ALL para a role da aplicação - viola o privilégio mínimo. Correção: CRUD em nível de tabela apenas.
- Copiar-colar índice de consultor - índice duplicado. Correção: screenshot de
pg_indexesno PR.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Sessão de pareamento | Primeiro PR SQL de júnior | Migração trivial rotineira |
| sqlfluff/sql-lint automatizado | Estilo e anti-padrões óbvios | Julgamento de EXPLAIN |
| Horário de atendimento de DBA | Equipe de alto volume | Bloquear pequenas correções |
FAQs
Exigir EXPLAIN para correção de uma linha?
Se a forma da query não mudou e não é um caminho crítico, anote a isenção. Qualquer alteração de filtro/join/índice em tabela grande requer EXPLAIN.
Quem é o revisor obrigatório para migrações com lock ALTO?
Pelo menos um DBA ou engenheiro sênior da lista de rotação. Regra de duas pessoas para produção se aplica.
Revisar SQL de seed/fixture?
Sim para PII e volume similar ao de produção. Seeds de desenvolvimento ainda não devem usar padrões de superusuário que a produção proíbe.
Relacionados
- Noções Básicas de Git para Trabalho com Banco de Dados - fluxo de branch
- Skill de Revisão EXPLAIN - rubrica de plano
- Skill de Segurança de Migração - pontuação de lock
- Pareamento em PRs de Query - revisão ao vivo
- Padrões de Revisão de Query - política da equipe
Versões da Stack: Esta página foi escrita para PostgreSQL 18.4 e stacks de aplicação usando migrações Flyway 10+.