EDSQLite
Banco de dados relacional embutido, inspirado no SQLite, escrito em Rust do zero.
Versão 0.14.0 · pré-lançamento · macOS e Linux
$ edsqlite loja.db
edsqlite> SELECT p.nome, sum(v.qtd) AS vendidos
...> FROM produtos AS p
...> JOIN vendas AS v ON v.produto = p.nome
...> GROUP BY p.nome ORDER BY vendidos DESC;
caneta|15
mochila|1
edsqlite> EXPLAIN QUERY PLAN SELECT * FROM vendas
...> WHERE produto = 'caneta';
QUERY PLAN
`--SEARCH vendas USING INDEX v_produto (produto=?)
É estável? Dá para usar?
Já dá para confiar
- SQL do dia a dia: CREATE TABLE/INDEX, INSERT, UPDATE, DELETE e SELECT com WHERE, ORDER BY e LIMIT.
- JOINs, GROUP BY, HAVING, DISTINCT e subconsultas.
CASE,CASTe as funções de textosubstr,replaceetrim.- Restrições:
NOT NULL,DEFAULT,UNIQUE,PRIMARY KEYeINTEGER PRIMARY KEY. - Commit atômico mesmo com queda de energia ou
kill -9. - Várias conexões ao mesmo tempo, com locks e modo WAL.
- Resultados iguais aos do SQLite em mais de 8 milhões de consultas geradas e em 6 mil consultas do corpus oficial de testes do SQLite.
- Formato do arquivo congelado, com política de compatibilidade.
Ainda não
CHECK, chaves estrangeiras, LEFT JOIN, UNION, views, ALTER TABLE e muitas funções.- Locks no Windows.
O que já tem na 0.12
SQL com tipos do SQLite
Afinidade por coluna, as cinco classes de valor, aritmética, LIKE, IN, BETWEEN e as mesmas conversões do SQLite.
Índices e planner
Índices simples, compostos e UNIQUE. O planner escolhe buscas por índice ou por rowid e mostra tudo no EXPLAIN QUERY PLAN.
JOINs e agregação
JOIN ... ON, vírgula, CROSS JOIN, count, sum, avg, min, max, group_concat, GROUP BY, HAVING e DISTINCT.
Subconsultas
Escalares, IN (SELECT ...) e EXISTS, correlacionadas ou não.
Restrições
NOT NULL, DEFAULT, UNIQUE, PRIMARY KEY e INTEGER PRIMARY KEY, que é o próprio rowid, como no SQLite. PRAGMA table_info mostra tudo.
CASE, CAST e texto
CASE com e sem base, CAST para os cinco tipos e as funções substr, replace, trim, ltrim e rtrim, com os detalhes do SQLite.
Transações duráveis
BEGIN/COMMIT/ROLLBACK com rollback journal. Testado com milhares de crashes simulados e kill -9 de verdade.
Concorrência e WAL
Várias conexões, em threads ou processos, com busy_timeout. No modo WAL, leitores não bloqueiam o escritor.
Comandos preparados
prepare, bind e step, com parâmetros ?, ?N e :nome. Um comando preparado é recompilado sozinho quando outra conexão muda o schema.
Formato estável
O arquivo está documentado byte a byte e congelado. Os códigos de erro têm os números do SQLite (BUSY, CONSTRAINT, NOTADB...).
API C
No formato da API C do SQLite (edsqlite_open, prepare_v2, step, bind_*, column_*), com header para C e C++. É o caminho para drivers em outras linguagens.
Instalação
- Baixe o
.tar.gzdo seu sistema na última versão. - Extraia e coloque o
edsqlitenum diretório do seuPATH:
tar xzf edsqlite-0.14.0-macos-arm64.tar.gz
sudo mv edsqlite /usr/local/bin/
edsqlite --version
No macOS, o binário não é assinado pela Apple. Se o sistema bloquear a execução, rode uma vez:
xattr -d com.apple.quarantine /usr/local/bin/edsqlite
DBeaver: baixe o edsqlite-jdbc-<versão>.jar e cadastre-o uma vez em Database → Driver Manager → New (Driver Type Generic, Class Name br.edsqlite.jdbc.EDSQLiteDriver, URL Template jdbc:edsqlite:{file}, Embedded, e o .jar em Libraries). Depois, é como no SQLite: nova conexão, EDSQLite, o caminho do arquivo e Finish. Não precisa de Java instalado: o driver roda no Java do DBeaver.
Biblioteca C: os pacotes edsqlite-capi-<versão>-<sistema>.tar.gz trazem include/edsqlite.h e a biblioteca (.dylib ou .so, e .a), para usar o EDSQLite de C, C++ ou de um driver. A de Linux usa a glibc 2.34 ou mais nova (Ubuntu 22.04+, Debian 12+, RHEL 9+).
Uso: edsqlite dados.db abre (ou cria) um banco; edsqlite sem argumento usa um banco temporário em memória. Os comandos terminam em ;. Comandos do REPL: .headers on|off, .tables, .indexes e .exit. Também dá para rodar um script: edsqlite dados.db < script.sql.
Como é testado
| Teste | O que garante |
|---|---|
| Diferencial contra o SQLite 3.53 | SQL aleatório (expressões, índices, JOINs, agregação, subconsultas) nos dois bancos, com resultado idêntico: mais de 16 milhões de consultas e comandos, nenhuma divergência. |
| Crash em cada operação de I/O | O banco fica sempre no estado de antes ou de depois da transação, nos dois modos de journal. |
kill -9 real | Nenhuma transação pela metade nem perdida depois de confirmada. |
| Stress de concorrência | Escritor e leitores em threads e em processos, sem leitura inconsistente nem deadlock. |
| Relatórios estilo TPC-H | Consultas de relatório sobre 10 mil itens dão exatamente o resultado do SQLite. |
| sqllogictest do SQLite | 6106 consultas do corpus oficial de conformidade do SQLite, com as respostas que o próprio SQLite deu. |
| Queda de energia em toda a suíte | Cada script de teste roda com um crash simulado em cada operação de I/O: uns 5800 crashes a cada execução. |
| Fuzzing | SQL arbitrário e arquivos de banco corrompidos, todas as noites: nunca um panic, só erros. |
| Cobertura | 94,7% das linhas cobertas pelos testes, com metas mínimas nos módulos de armazenamento e da VM. |
Roadmap
v0.1 a v0.12 concluídas
Parser, VM de bytecode, B-tree em disco, tipos com afinidade, índices e planner, transações duráveis, concorrência com WAL, JOINs, agregação, subconsultas, CASE, CAST, funções de texto, restrições e, na 0.12, tudo o que estava planejado para a v1.0 (abaixo).
v1.0 · API estável e testes obsessivos pronta na 0.12
O que faltava para chamar de versão estável.
- Formato do arquivo congelado, documentado byte a byte e com política de compatibilidade: versão no cabeçalho, versão futura recusada sem tocar no arquivo, semver na API.
- API com parâmetros:
prepare,bind,step,resetefinalize, com?,?Ne:nomeno SQL, sem precisar montar SQL como texto. - Fuzzing com
cargo-fuzz: SQL arbitrário e arquivos de banco corrompidos, sempre sem panic. - Códigos de erro estáveis, com os números do SQLite.
- Recompilação automática de um comando preparado quando o schema muda.
- Queda de energia simulada em toda a suíte de testes, não só nas transações.
- Cobertura de testes medida: 94,7% das linhas, acima da meta de 90% nos módulos de armazenamento e da VM.
- 6106 consultas do corpus de conformidade sqllogictest do SQLite como teste.
- Uma API C no formato da do SQLite, com header para C e C++.
Driver JDBC (DBeaver) pronto
Para abrir bancos EDSQLite em ferramentas como o DBeaver.
- Pronto: vários comandos em execução ao mesmo tempo na mesma conexão (ler um resultado enquanto roda outra consulta), como as ferramentas de banco fazem.
- Pronto:
last_insert_rowid, para as chaves geradas de um INSERT. - Pronto: biblioteca e API C nos downloads das releases.
- Pronto: o driver JDBC (
edsqlite-jdbc-<versão>.jar), para abrir bancos EDSQLite no DBeaver como se abre um SQLite.
Recursos de SQL que faltam
Os mais usados primeiro.
- Restrições:
CHECK,AUTOINCREMENT, chaves estrangeiras eON CONFLICT/REPLACE. - Consultas:
LEFT JOIN,UNION/INTERSECT/EXCEPT, subconsultas no FROM,WITH(CTE),USING/NATURAL,INSERT ... SELECT. - Funções:
instr,printf, as de data e hora e as de janela. - Schema:
ALTER TABLE(renomear e acrescentar colunas),CREATE VIEW, triggers,COLLATE, índices DESC.
Plataformas e desempenho
- Locks no Windows. Hoje eles só existem em Unix (macOS e Linux); no Windows, duas conexões no mesmo arquivo não se protegem uma da outra.
- Instalação por Homebrew e pacote para Linux.
- Planner com estatísticas (
ANALYZE), índices cobertos e busca comIN. - Transações maiores que a memória e ORDER BY com espaço em disco.
VACUUM, para devolver ao disco o espaço livre.
Depois
- Busca de texto completo, JSON e funções definidas pelo usuário.