Banco de Dados

10 abr, 2017

Defql: Consultas SQL como funções Elixir

Publicidade

O mundo Elixir é funcional. Não há objetos ou instâncias. Nesse caso, eu me fiz uma pergunta.

Preciso de ORM?

Minha resposta a essa pergunta é não.

Preciso de dados. Dados puros que vêm diretamente do banco de dados. Outra pergunta que vem à minha mente.

Preciso de um DSL para consultar banco de dados?

Outra resposta negativa.

Temos uma ótima linguagem criada para consultar o banco de dados. SQL, lembra?

E se eu pudesse criar uma função Elixir que tenha um corpo SQL? E se eu pudesse usar essa função exatamente como qualquer outra função do Elixir? Seria ótimo, não é?

Podemos arquivar isso usando o sistema macro muito poderoso do Elixir. No entanto, essa também é uma boa maneira de aprender como as macros do Elixir funcionam.

Para arquivar isso, eu comecei a escrever Defql. Defql é um pacote Elixir que fornece uma maneira simples de definir funções com linguagem SQL. Como ele funciona?

Consultando banco de dados

Esse pacote fornece a macro defquery. Com ela, você pode definir a função que contém uma consulta SQL. Por exemplo:

defmodule UserQuery do
  use Defql
 
  defquery get_by_blocked(blocked) do
    "SELECT * FROM users WHERE blocked = $blocked"
  end
end

Parece muito limpo, é fácil de ler e a melhor parte dele é que ele suporta parâmetros. Brilhante!

Chamar essa função também é muito simples.

Dependendo do parâmetro fornecido, obteremos usuários bloqueados ou desbloqueados.

UserQuery.get_user(false) # => {:ok, []} 
UserQuery.get_user(true) # => {:ok, []}

Agora nós podemos consultar facilmente nosso banco de dados e encontrar um resultado.

E quanto a INSERT, UPDATE e DELETE? Boa pergunta! Você pode criar essas consultas com defquery, mas há outro método.

CRUD

Esse pacote também contém outras macros. Dê uma olhada neste exemplo:

defmodule UserQuery do
  use Defql

  defselect get(conds), table: :users
  definsert add(params), table: :users
  defupdate update(params, conds), table: :users
  defdelete delete(conds), table: :users
end

O que eles farão? Essas macros irão criar funções CRUD comuns. Então, você não precisa escrever cada consulta com o SQL. Algumas simples são criadas para você, como esta. Como posso invocá-las? Aqui está um exemplo:

UserQuery.get(id: "3") # => {:ok, [%{...}]}
UserQuery.add(name: "Smbdy") # => {:ok, [%{...}]}
UserQuery.update([name: "Other"],[id: "2"]) # => {:ok, [%{...}]}
UserQuery.delete(id: "2") # => {:ok, [%{...}]}

Configuração

A configuração também é uma tarefa fácil. Agora mesmo você pode usá-la de duas maneiras.

Com conexão Ecto existente:

config :defql, connection: [
  adapter: Defql.Adapter.Ecto.Postgres,
  repo: Taped.Repo
]

Como uma conexão autônoma:

CÓDIGO

O que falta?

Claro, é um estágio muito inicial, mas o suporte para postgres funciona bem. Há poucas coisas que estão faltando:

  • Suporte para MySQL
  • Suporte para IN com array % {id: [1,2,3]}
  • Adaptador ECTO de limpeza
  • Suporte para erros de banco de dados

Resumo

Usando Defql, temos uma maneira muito clara, simples e poderosa de interagir com um banco de dados.

Links

Espero que tenha sido útil para você. Obrigado por ler!

***

Michał Kalbarczyk faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://blog.fazibear.me/sql-queries-as-elixir-functions-5f8b1d67169e.