Study Notes
Data

SGBDs Drivers

Em Sistemas Operacionais um driver é um software que faz a ponte entre o OS e o hardware específico (ex: driver da placa de vídeo, da placa de rede, teclado e etc). Analogamente, "drivers de bancos de dados" seriam a ponte entre uma aplicação e um SGBD.

É a biblioteca/componente que implementa/segue o protocolo de aplicação específico de cada SGBD.

Um driver de um SGBD seria o "cliente de baixo nível" e a aplicação (DBeaver, API Node js, etc) seria o "cliente de alto nível".

Pode-se dizer que é um SGBD driver é um driver de software, um conector/ adapter de aplicação. Ou seja, um cliente de protocolo de aplicação. Assim como para o protocolo HTTP teriam diferentes "drivers" (Requests do python, Fetch API do JS, etc) ou para SMTP (Nodemailer, smtplib,...) ou SSH (paramiko do python). São todos bibliotecas que facilitam a comunicação na rede entre programas que usam determinados protocolos de aplicação. O fato de chamar de "drive" apenas as bibliotecas que fazem isso para SGBDs tem origem histórica. O termo "driver" vem de device drivers/ do hardware. E SGBDs eram no inicio tratados como devices de armazenamento externo (como impressoras, HDs, etc) que precisavam de "drivers" também para se conectar. As APIs que vieram (JDBC e ODBC) ajudaram a formular e divulgar esse conceito de driver para SGBD drivers.

Funcionamento

Qualquer aplicação que precisa ler/escrever em um SGBD precisa interagir com um driver antes. Geralmente, o processo do envio de queries da aplicação (app) até o SGBD funciona da seguinte forma:

Aplicação monta a request

A app (Node js, Java, Power BI, DBeaver, Data Grip,...) pega a query escrita (como "SELECT nome, email FROM clientes WHERE id = 10;", no caso de RDBMS), as credenciais de acesso (host, port, user e password) e outros parâmetros e se comunica com o Driver através de uma API. Exemplo:

String url = "jdbc:postgresql://localhost:5432/meubanco";
String usuario = "meuusuario";
String senha = "minhasenha";

try (Connection conn = DriverManager.getConnection(url, usuario, senha)){
    System.out.println("Conexão estabelecida com sucesso!");
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT id, nome FROM usuarios");

No caso do exemplo em Java, a JDK só vem com a API JDBC. Os drivers concretos para cada SGBD são dependências externas, uma biblioteca .jar que contém a lógica para comunicar com aquele SGBD (tipo postgresql-42.7.3.jar).

Abstração do Driver

O Driver recebe a requisição da api (no exemplo JDBD API) e traduz para o protocolo de aplicação específico do SGBD. (Ou seja, os parâmetros da query são serializados (representados em strings de bytes) no formato certo, cuidando de autenticação, e etc). Cada SGBD tem seu próprio protocolo de aplicação, por exemplo:

  • Redis -> RESP (Redis Serialization Protocol)
  • PostgreSQL -> PostgreSQL Wire Protocol
  • Microsoft SQL Server -> Tabular Data Stream (TDS)
  • MySQL / MariaDB -> MySQL Client/Server Protocol Ou seja, o driver age como um middleware entre a aplicação que faz a query e o SGBD server. Então os dados são sempre traduzidos tanto na request quanto na response.

Drivers vs Database Clients

Database clients são softwares que oferecem uma interface gráfica ou por command line para interagir/ executar queries para os SGBDs. Exemplos:

DB ClientSGBDInterface
[[PostgreSQL#pgAdmin|pgAdmin]][[PostgreSQL]]GUI
[[PostgreSQL#psql|psql]][[PostgreSQL]]CLI
cqlshCassandraCLI
DBeaver*GUI
DataGrip*GUI
A verdade é que esses programas são feitos por LP (como Java) que usam uma API padrão (como a JDBC API) para carregar e, de forma generalizada, se comunicarem com SGBD drivers específicos. Ou seja, no final das contas, a lógica para a comunicação com o SGBD target está toda na implementação do drive ("o verdadeiro cliente").

Especificações de Drivers

São abstrações que oferecem um conjunto de regras (um contrato) de como os drivers (bibliotecas específicas de cada SGBD que encapsulam a lógica da camada de aplicação) devem seguir. Dessa forma, diferentes drivers que seguem uma mesma especificação conseguem ser facilmente mudados já que teriam a mesma abstração (API) chamando seus métodos. As especificações de drivers resolvem o problema de desacoplamento, exemplo: Se um programa (o DBeaver é um bom exemplo) precisa conectar a SGBDs distintos (MySQL, PostgreSQL, Mongo DB, etc) teria que escrever os drivers de cada um. No entanto, como os drivers são libs que seguem uma especificação, diferentes drivers que seguem determinada especificação podem ser trocados facilmente e serem chamados através das mesmas assinaturas.

JDBC API

Java Database Connectivity é um conjunto de interfaces/classes Java (já vem na própria JDK, nos packages java.sql e javax.sql) que definem um contrato que os drivers devem seguir para serem compatíveis com o ecossistema Java. É, obviamente, exclusiva do ambiente Java. JDBC é padrão no mercado porque Java tem sido a espinha dorsal do desenvolvimento de software corporativo por décadas. Nem tanto que DB Clients (como DataGrip, DBeaver, etc), Big Data frameworks (como Apache Spark) escolherem o Java por ser multiplataforma e o que ajudou o JDBC API virar padrão.

DB-API 2

Node js e a Não-Especificação

O Node js (como alguns outros ecossistemas) não possui especificação de drivers centralizados, de forma formal. A única regra, devido a natureza assíncrona é que os drivers devem ser não-bloqueantes (utilizando o event loop do node). De resto, cada implementação de driver possuí uma API diferente. Nesse caso, frente a esse "zoológico" de bibliotecas diferentes para conectar nos SGBDs, utilizar ORMs/ODMs (Sequelize, TypeORM, Prisma,...) para servirem como camada de padronização é uma boa escolha. Nesse caso, essas frameworks criam uma especificação (não de driver) que assume a responsabilidade de adaptar a diferentes tipos de drivers (pelo menos aqueles suportados).

ODBC

Open Database Connectivity é o padrão multiplataforma da microsoft (desenvolvido no inicio de 1990). Ou seja, o ODBC (assim como os tópicos acima) não é um programa, é uma especificação. (Embora foi projetado para funcionar com Driver Manager (um programa em si) desde o início)

O programa que executa/chama os drivers que seguem essa implementação é chamado de ODBC Driver manager. Esse programa não é exclusivo do Windows OS, apesar de já vim embutido (ODBC Data Sources, odbcad32.exe). Para Unix/linux/macOS existe o unixODBC. (Como distros Linux seguem uma filosofia de instalação mínima, softwares para fins específicos como a conectividade com SGBDs precisam ser instalados manualmente).

Como é feito para ser agnóstico de linguagem, essa especificação é feita na linguagem C, para ser mais universal possível (praticamente toda LP (python, Java, Go,...) conseguem chamar funções escritas em C. Além da compatibilidade com outras LP que C trás, os drivers implementando ODBC sendo escritos em C/C++ melhoram a performance.

ODBC Driver Manager

É um programa (altamente eficiente) separado que interage com os SGBDs drivers. Ele permite que aplicações (Power BI, Excel, python, Java e etc), em diferentes LP, consigam se comunicar com os drivers que implementam a especificação ODBC. Sendo assim, os desenvolvedores dos SGBDs não precisam fazer drivers específicos para cada linguagem. Eles fazem em C/C++ seguindo o ODBC (que é uma especificação padrão de mercado). Dessa forma, o programa que chama os outros drivers disponíveis no sistema é o ODBC Driver Manager. Embora, em teoria, seja possível as LPs conseguirem chamar/executar diretamente os drivers ODBC que são escritos em C, ter um programa específico para isso é uma boa decisão de arquitetura. Dessas forma, as LPs precisam apenas implementar uma lib wrapper/binding (como o pyodbc) da LP para C para comunicar com o programa ODBC driver manager. E, dessa forma, o próprio ODBC driver manager abstraí a localização daquele driver, mantendo registro onde no sistema todos os drivers estão instalados.

# Com Driver Manager
pyodbc.connect("DRIVER={PostgreSQL ODBC Driver};SERVER=localhost;...")

# Sem Driver Manager (hipotético)
pyodbc.connect("/usr/lib/psql-odbc.so", "SERVER=localhost;...")  # caminho hardcoded!

Além disso, o driver manager consegue implementar um pool de conexões entre drivers (mais eficiente que cada aplicação fazer seu próprio pool), resolver problemas de versionamento/compatibilidade e fornecer logging centralizado (trace de todas as chamadas em um lugar só).

odbc.png

Linux Installation - unixODBC

sudo apt update
sudo apt install unixodbc unixodbc-dev
  • unixodbc: é o pacote principal com o unixODBC Driver Manager.
  • unixodbc-dev: não é obrigatório baixar mas previne "dor de cabeça". é um pacote contendo os header files .h.

DSN - Data Source Name

É um apelido/alias/atalho que guarda os parâmetros de conexão:

  • O path para o ODBC Driver
  • host, port, database, user e etc

Driver Properties

On this page