使用神奇Elixir SQL dust生成复杂的SQL查询

sssssstttt 8年前

来自: https://github.com/archan937/sql_dust

SqlDust

使用神奇Elixir SQL dust生成复杂的SQL查询,具有简单,强大和简便的特性。

Introduction

Every language has its commonly used libraries / gems / packages to interact with database. Ruby hasActiveRecord and Elixir hasEcto. They provide a lot of functionality which are very useful but when it comes to quickly and easily querying tabular data they require too much hassle:

  • you have to describe models representing tables (example)
  • you have to describe how to join tables ( example )
  • using the query DSL requires a bit of reading and understanding how to use it

Actually, you do not want to waste time specifying how to join tables and thinking about table aliases when you have followed the standard naming convention. And you do not want to think about putting a condition in the WHERE or HAVING statement.

The solution is to think in paths (e.g. company.tags.name ) and letting the package do the magic regarding joining table and to use SELECT statement aliases to determine HAVING statements.

Enter SqlDust . It makes it as easy and simple as possible for the developer to generate SQL queries:

  • no models setup
  • no joins specifications
  • no DSL to learn

Just focus on what really matters! ;)

An example

Based on standard naming conventions, SqlDust will determine how to join tables. You just have to specify from which resource (table) to query from and which columns to select using paths:

iex(1)> IO.puts SqlDust.from("users", %{select: ~w(id first_name company.category.name)})  SELECT    `u`.id,    `u`.first_name,    `company.category`.name  FROM users `u`  LEFT JOIN companies `company` ON `company`.id = `u`.company_id  LEFT JOIN categories `company.category` ON `company.category`.id = `company`.category_id    :ok  iex(2)>

Installation

To install SqlDust, please do the following:

  1. Add sql_dust to your list of dependencies in mix.exs :

    def deps do    [{:sql_dust, "~> 0.0.1"}]  end
  2. Ensure sql_dust is started before your application:

    def application do    [applications: [:sql_dust]]  end

Usage

Generating SQL queries has never been simpler. Just invoke the SqlDust.from/3 function. It accepts the following arguments:

  • resource (required) - Usually this is the table from which you want to query from
  • options (required) - A map containing info about what the query should contain (e.g. :select , :where , :group_by )
  • schema (optional) - A map containing info which overrule the defacto derived schema
options = %{    select: "id, name, COUNT(orders.id) AS order_count, GROUP_CONCAT(DISTINCT tags.name) AS tags, foo.tags",    group_by: "id",    where: ["name LIKE '%Paul%'", "order_count > 5", "foo.tags = 1"],    order_by: "COUNT(DISTINCT tags.id) DESC",    limit: 5  }    schema = %{    customers: %{      tags: %{        macro: :has_and_belongs_to_many      }    }  }    IO.puts SqlDust.from("customers", options, schema)    """  SELECT    `c`.id,    `c`.name,    COUNT(`orders`.id) AS order_count,    GROUP_CONCAT(DISTINCT `tags`.name) AS tags,    `foo`.tags  FROM customers `c`  LEFT JOIN orders `orders` ON `orders`.customer_id = `c`.id  LEFT JOIN customers_tags `tags_bridge_table` ON `tags_bridge_table`.customer_id = `c`.id  LEFT JOIN tags `tags` ON `tags`.id = `tags_bridge_table`.tag_id  LEFT JOIN foos `foo` ON `foo`.id = `c`.foo_id  WHERE (`c`.name LIKE '%Paul%') AND (`foo`.tags = 1)  GROUP BY `c`.id  HAVING (order_count > 5)  ORDER BY COUNT(DISTINCT `tags`.id) DESC  LIMIT 5  """

Enjoy using SqlDust! ^^

Testing

Run the following command for testing:

mix test

Every SqlDust feature is tested in test/sql_dust_test.exs .

Nice To Have

  • Query from the database
  • Use database connection and/or Ecto to derive defacto schema even better
  • Support querying with an Ecto model SqlDust.from(Sample.Weather)

TODO

  • Add additional documentation to the README
  • Add doc tests for internal functions

License

Copyright (c) 2016 Paul Engel, released under the MIT License

http://github.com/archan937http://推ter.com/archan937pm_engel@icloud.com