Skip to content

Instantly share code, notes, and snippets.

@moxley
Created July 15, 2016 22:39
Show Gist options
  • Save moxley/d0ffff7e433d5a338247f563c988c298 to your computer and use it in GitHub Desktop.
Save moxley/d0ffff7e433d5a338247f563c988c298 to your computer and use it in GitHub Desktop.
Showing there is no way to dynamically build an Ecto query where the schemas involved and number of joins are only known at runtime
defmodule MyApp.JoinTest do
def add_join(query, qual, join_schema, join_key, _other_schema, other_key) do
# -------------------------->| |<-------------------------- #
Ecto.Query.join(query, qual, [t0], t1 in ^(join_schema), field(t1, ^join_key) == field(t0, ^other_key))
# -------------------------->| |<-------------------------- #
end
test "add_join" do
query =
Ecto.Query.from(Cart)
|> add_join(:inner, CartItem, :cart_id, Cart, :id)
|> add_join(:inner, Product, :id, CartItem, :product_id)
expected = Ecto.Query.from(
t0 in Cart,
join: t1 in CartItem,
on: t1.cart_id == t0.id,
join: t2 in Product,
on: t2.id == t1.product_id)
assert inspect(query) == inspect(expected)
# 1) test add_join (MyApp.JoinTest)
# test/lib/my_app/join_test.exs
# Assertion with == failed
# code: inspect(query) == inspect(expected)
# lhs: "#Ecto.Query<from c0 in MyApp.JoinTest.Cart, join: c1 in MyApp.JoinTest.CartItem, on: c1.cart_id == c0.id, join: p in MyApp.JoinTest.Product, on: p.id == c0.product_id>"
# rhs: "#Ecto.Query<from c0 in MyApp.JoinTest.Cart, join: c1 in MyApp.JoinTest.CartItem, on: c1.cart_id == c0.id, join: p in MyApp.JoinTest.Product, on: p.id == c1.product_id>"
end
end
@moxley
Copy link
Author

moxley commented Jul 15, 2016

It is possible to make every part of a join clause dynamic, except for the bindings (circled in screenshot). The bindings and the number of bindings must be determined at compile time. This makes it (nearly) impossible to create a library that generates arbitrary queries based on runtime data.

dynamic-join

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment