3

Elixir的世界是函数的世界. 这里没有对象, 没有实例. 在这种情况下, 我问我自己一个问题.

我真的需要ORM吗?

我的答案是: NO.

我需要数据. 直接来自于数据库的纯粹的数据. 另一个我思考的问题是:

我需要一个查询数据库的DSL吗?

答案同样是否定的: NO.

其实, 我们已经有了一个现成的数据库查询语言, SQL, 记得么?

如果我创建一个包含SQL的Elixir函数. 如果我们像使用其他函数一样使用这个函数.

我们可以使用Elixir的宏系统来达到这个目的. 同时也是一个学习Elixir宏的好机会.

为此我开始编写 Defql. Defql是一个简单的Elixir包, 它提供了一个方式用SQL语言来定义函数. 它是如何工作的?

查询数据库

这个包提供了一个defquery宏. 用它可以定义包含SQL查询的Elixir函数. 比如:

defmodule UserQuery do
  use Defql

  defquery get_by_blocked(blocked) do
    "SELECT * FROM users WHERE blocked = $blocked"
  end
end

看起来非常干净整洁, 易于阅读. 并且最有用的是, 它支持参数.

调用这类函数也是非常简单的. 取决于给定的参数, 我们可以锁定/解锁用户.

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

CRUD

这个包还包含其他的宏, 看一下这个例子:

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

这些宏将会床公共的CRUD函数. 因此不必编写每一个SQL查询. 如何调用他们?

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

配置

配置也是一个简单的工作. 现在你可以用两种方式使用它.

使用现有的Ecto连接:

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

作为一个独立的连接

config :defql, connection: [
  hostname: "localhost",
  username: "username",
  password: "password"
  database: "dbname",
  pool: DBConnection.Poolboy,
  pool_size: 1
]

缺什么?

当然, 它还在非常早期的开发阶段. 但是postgres支持得很好. 下面是缺少的部分:

  • MySQL支持

  • IN的支持

  • Ecto 适配器

  • 支持数据库错误

摘要

使用 Defql, 我们有一个非常干净, 简单和强大的方式与数据库交互.

结语

这个工具库特别适合于在团队内有DBA的情况下使用, DBA已经帮你写好了所有的业务SQL, 你只需要把SQL参数化就可以了, 不用自己写数据操作相关的功能的时候特别有用也特别好维护. 如果团队内没有DBA, 还是建议使用Ecto这类的的库.


developerworks
1.7k 声望266 粉丝