Integrando Zig com Bancos de Dados

Integrando Zig com Bancos de Dados

Zig não possui ORMs ou drivers nativos para bancos de dados, mas sua interoperabilidade nativa com C permite usar qualquer biblioteca C de banco de dados diretamente. Neste artigo, exploramos integração com SQLite, PostgreSQL e Redis.

SQLite — Embutido

SQLite é a opção mais natural para Zig, pois pode ser compilado junto com sua aplicação:

const c = @cImport({
    @cInclude("sqlite3.h");
});
const std = @import("std");

const Database = struct {
    db: *c.sqlite3,

    pub fn abrir(caminho: [*:0]const u8) !Database {
        var db: ?*c.sqlite3 = null;
        if (c.sqlite3_open(caminho, &db) != c.SQLITE_OK) {
            return error.ErroAbrirBanco;
        }
        return .{ .db = db.? };
    }

    pub fn executar(self: Database, sql: [*:0]const u8) !void {
        var err_msg: ?[*:0]u8 = null;
        if (c.sqlite3_exec(self.db, sql, null, null, &err_msg) != c.SQLITE_OK) {
            if (err_msg) |msg| c.sqlite3_free(msg);
            return error.ErroSQL;
        }
    }

    pub fn fechar(self: Database) void {
        _ = c.sqlite3_close(self.db);
    }
};

pub fn main() !void {
    var db = try Database.abrir("app.db");
    defer db.fechar();

    try db.executar(
        \\CREATE TABLE IF NOT EXISTS usuarios (
        \\  id INTEGER PRIMARY KEY AUTOINCREMENT,
        \\  nome TEXT NOT NULL,
        \\  email TEXT UNIQUE NOT NULL
        \\)
    );

    try db.executar("INSERT INTO usuarios (nome, email) VALUES ('Ana', 'ana@exemplo.com')");
}

PostgreSQL via libpq

const c = @cImport({
    @cInclude("libpq-fe.h");
});

const PgConn = struct {
    conn: *c.PGconn,

    pub fn conectar(conn_string: [*:0]const u8) !PgConn {
        const conn = c.PQconnectdb(conn_string) orelse return error.ConexaoFalhou;
        if (c.PQstatus(conn) != c.CONNECTION_OK) {
            c.PQfinish(conn);
            return error.ConexaoFalhou;
        }
        return .{ .conn = conn };
    }

    pub fn query(self: PgConn, sql: [*:0]const u8) !*c.PGresult {
        const result = c.PQexec(self.conn, sql) orelse return error.QueryFalhou;
        if (c.PQresultStatus(result) != c.PGRES_TUPLES_OK) {
            c.PQclear(result);
            return error.QueryFalhou;
        }
        return result;
    }

    pub fn desconectar(self: PgConn) void {
        c.PQfinish(self.conn);
    }
};

Conclusão

A interoperabilidade nativa de Zig com C permite usar qualquer biblioteca de banco de dados existente sem overhead de FFI. SQLite compilado junto com a aplicação é a opção mais ergonômica, enquanto PostgreSQL e Redis são acessíveis via suas bibliotecas C.

Conteúdo Relacionado

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.