Pular para o conteúdo

Cada motor

O que a interface comum cobre, e o que só existe em cada um.

A interface comum cobre o que faz sentido em todos: conectar, consultar, fechar. O resto cada motor expõe pelo que ele é — um ORM que finge que Redis é uma tabela produz código que parece portável e não é.

SQLite#

Roda dentro do processo. É o banco de teste que não deixa rastro:

dataforge
adopt Forge

db := Forge.memoria()                 // ou Forge.conectar("dados.db")
Forge.executar(db, "create table t (id integer primary key, n integer)")
Forge.de(db, "t").inserir({"n": 1})
assert Forge.de(db, "t").contar() is 1

Duas coisas que o Forge liga e o SQLite deixa desligadas por padrão: chave estrangeira (senão a restrição existe só no papel) e WAL (senão um leitor bloqueia o escritor, e um servidor trava com carga leve).

PostgreSQL#

Os tipos voltam convertidos: jsonb vira vault, array vira cluster, boolean vira yes/no.

dataforge
// db := Forge.conectar("postgres://usuario:senha@localhost/app")
//
// Forge.executar(db, """
//     create table pessoas (
//         id serial primary key,
//         nome text not null,
//         dados jsonb,
//         tags text[]
//     )
// """)
//
// Forge.executar(db,
//     "insert into pessoas (nome, dados, tags) values (?, ?, ?)",
//     ["Ana", {"cor": "azul"}, ["a", "b"]])
//
// linha := Forge.primeiro(db, "select * from pessoas")
// out linha["dados"]["cor"]        // "azul" — vault de verdade
// out linha["tags"][0]             // "a"    — cluster de verdade

RETURNING funciona e devolve as linhas:

dataforge
// nova := Forge.executar(db,
//     "insert into pessoas (nome) values (?) returning id, nome",
//     ["Bia"])
// out nova[0]["id"]

MySQL e MariaDB#

O mesmo driver serve os dois — o MariaDB nasceu de um fork e manteve o protocolo. O que muda é a autenticação padrão.

dataforge
// db := Forge.conectar("mysql://root:senha@localhost/app")
// out db.ultimo_id()        // o id gerado pelo último auto_increment

Redis#

Não tem SQL, e fingir que tem seria mentir. O que ele tem é chave-valor, e é isso que a interface expõe:

dataforge
// db := Forge.conectar("redis://localhost")
//
// db.comando("SET", "usuario:1", "Ana")
// out db.comando("GET", "usuario:1")
// db.comando("EXPIRE", "usuario:1", 60)
//
// db.comando("RPUSH", "fila", 1, 2, 3)
// out db.comando("LRANGE", "fila", 0, -1)

Pipeline é a otimização mais eficaz com Redis. Cem comandos em cem idas custam cem vezes a latência da rede; numa ida só, custam uma:

dataforge
// respostas := db.pipeline([
//     ["SET", "a", "1"],
//     ["SET", "b", "2"],
//     ["MGET", "a", "b"]
// ])
// out respostas[2]        // ["1", "2"]

MongoDB#

Documentos, não tabelas. O _id sai como texto e a busca por ele aceita texto — sem essa conversão, procurar por id nunca acharia nada, e não haveria erro, só um resultado vazio:

dataforge
// db := Forge.conectar("mongodb://localhost/app")
//
// r := db.inserir("pessoas", [
//     {"nome": "Ana", "idade": 30},
//     {"nome": "Bia", "idade": 25}
// ])
//
// out db.achar("pessoas", {"idade": {"$gt": 26}})
// out db.achar_um("pessoas", {"_id": r["ids"][0]})
// db.atualizar("pessoas", {"nome": "Bia"}, {"idade": 26})
// out db.contar("pessoas")
//
// out db.agregar("pessoas", [
//     {"$group": {"_id": void, "media": {"$avg": "$idade"}}}
// ])
//
// db.criar_indice("pessoas", "nome", unico := yes)

O que é comum a todos#

SQLitePostgresMySQLRedisMongo
conectar
ping, versao, fechar
consultar / executarcrudocumento
construtor de consultas
ORM
transaçõesMULTI
tabelas / colunascolecoes