Skip to content

Commit

Permalink
Merge branch 'release/0.1.2'
Browse files Browse the repository at this point in the history
- Closes #6: Support for where/in queries
  • Loading branch information
evadne committed Oct 3, 2020
2 parents 64b1e7f + d3a4ef3 commit 51a4b4b
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 16 deletions.
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Etso

## Overview

Etso is an [ETS][erlang-ets] adapter, allowing you to use `Ecto` schemas with ETS tables.
**Etso** is an [ETS][erlang-ets] adapter, allowing you to use `Ecto` schemas with ETS tables.

Within this library, a bare-bones Ecto Adapter is provided. The Adapter transparently spins up ETS tables for each Ecto Repo and Schema combination. The tables are publicly accessible to enable concurrency, and tracked by reference to ensure encapsulation. Each ETS table is spun up by a dedicated Table Server under a shared Dynamic Supervisor.

Expand Down Expand Up @@ -54,18 +52,22 @@ The following features, for example, are missing:

Using Etso is a two-step process. First, include it in your application’s dependencies:

defp deps do
[
{:etso, "~> 0.1.1"}
]
end
```elixir
defp deps do
[
{:etso, "~> 0.1.2"}
]
end
```

Afterwards, create a new `Ecto.Repo`, which uses `Etso.Adapter`:

defmodule MyApp.Repo do
@otp_app Mix.Project.config()[:app]
use Ecto.Repo, otp_app: @otp_app, adapter: Etso.Adapter
end
```elixir
defmodule MyApp.Repo do
@otp_app Mix.Project.config()[:app]
use Ecto.Repo, otp_app: @otp_app, adapter: Etso.Adapter
end
```

Once this is done, you can use any Schema against the Repo normally, as you would with any other Repo. Check out the [Northwind modules][northwind] for an example.

Expand All @@ -75,9 +77,11 @@ Originally, Etso was created to answer the question of whether ETS and Ecto can

*If you have other Use Cases for this library, please add it here with a Pull Request.*

- The [Erlef Website](https://github.com/erlef/website) is using Etso to cache and query news and event posts that are parsed and imported into the Repo on application startup.

## Further Note

This repository is extracted from a prior project [ETS Playground][evadne-ets-playground], which was created to support my session at ElixirConf EU 2019, [*Leveraging ETS Effectively.*][evadne-ets-deck]
This repository is extracted from a prior project [ETS Playground][evadne-ets-playground], which was created to support a session at ElixirConf EU 2019, [*Leveraging ETS Effectively.*][evadne-ets-deck]

Specifically, this library was created to illustrate the point that ETS can serve as a scalable storage layer for data which changes infrequently. Check out the [Northwind Importer][northwind-importer] for an example.

Expand All @@ -95,10 +99,14 @@ The Author also wishes to thank the following individuals:

- [David Schainker](https://github.com/schainks), for initial reviews, and for finding uses for this library.

- [Masanori Iwasaki][curi1119], for [support of `for…in` queries][pr-6].

[erlang-ets]: http://erlang.org/doc/man/ets.html
[northwind]: https://github.com/evadne/etso/tree/master/test/support/northwind
[northwind-importer]: https://github.com/evadne/etso/tree/master/test/support/northwind/importer.ex
[northwind-repo-test]: https://github.com/evadne/etso/blob/master/test/northwind/repo_test.exs
[evadne-ets-playground]: https://github.com/evadne/ets-playground
[evadne-ets-deck]: https://speakerdeck.com/evadne/leveraging-ets-effectively
[wojtekmach]: https://github.com/wojtekmach
[curi1119]: https://github.com/curi1119
[pr-6]: https://github.com/evadne/etso/pull/6
8 changes: 6 additions & 2 deletions lib/etso/ets/match_specification.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,16 @@ defmodule Etso.ETS.MatchSpecification do
field_name
end

defp resolve_field_values(params, {:^, [], indices}) do
for index <- indices do
defp resolve_field_values(params, {:^, [], [index, count]}) do
for index <- index..(index + count - 1) do
Enum.at(params, index)
end
end

defp resolve_field_values(params, {:^, [], [index]}) do
Enum.at(params, index)
end

defp get_field_index(field_names, field_name) do
1 + Enum.find_index(field_names, fn x -> x == field_name end)
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Etso.MixProject do
def project do
[
app: :etso,
version: "0.1.1",
version: "0.1.2",
elixir: "~> 1.8",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
Expand Down
46 changes: 46 additions & 0 deletions test/northwind/repo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,52 @@ defmodule Northwind.RepoTest do
|> Repo.all()
end

test "Where In None" do
employee_ids = []

Model.Employee
|> where([x], x.employee_id in ^employee_ids)
|> select([x], x.employee_id)
|> Repo.all()
|> Enum.sort()
|> (&assert(&1 == employee_ids)).()
end

test "Where In One" do
employee_ids = [3]

Model.Employee
|> where([x], x.employee_id in ^employee_ids)
|> select([x], x.employee_id)
|> Repo.all()
|> Enum.sort()
|> (&assert(&1 == employee_ids)).()
end

test "Where In Multiple" do
employee_ids = [3, 5, 7]

Model.Employee
|> where([x], x.employee_id in ^employee_ids)
|> select([x], x.employee_id)
|> Repo.all()
|> Enum.sort()
|> (&assert(&1 == employee_ids)).()
end

test "Where In Nested" do
employee_ids = [3, 5, 7]
employee_first_names = ["Janet"]

Model.Employee
|> where([x], x.employee_id in ^employee_ids)
|> where([x], x.first_name in ^employee_first_names)
|> select([x], x.employee_id)
|> Repo.all()
|> Enum.sort()
|> (&assert(&1 == [3])).()
end

test "Select Where" do
Model.Employee
|> where([x], x.title == "Vice President Sales" and x.first_name == "Andrew")
Expand Down
1 change: 1 addition & 0 deletions test/support/northwind/model/shipper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Northwind.Model.Shipper do
schema "shippers" do
field :company_name, :string
field :phone, :string

# field :shipper_id, :integer

has_many :orders, Model.Order,
Expand Down
1 change: 1 addition & 0 deletions test/support/northwind/model/supplier.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule Northwind.Model.Supplier do
field :company_name, :string
field :contact_name, :string
field :contact_title, :string

# field :supplier_id, :integer

embeds_one :address, Model.Address
Expand Down

0 comments on commit 51a4b4b

Please sign in to comment.