This is Product.relationships code.
end
attributes do
uuid_v7_primary_key :id
attribute :is_adult_only, :boolean, allow_nil?: false, public?: true
end
relationships do
has_many :inventories, SevenEleven.Inventory, destination_attribute: :product_id
has_many :stores, SevenEleven.Store do
no_attributes? true
filter expr(inventories.product_id == parent(id))
end
has_many :stores_alt1, SevenEleven.Store do
no_attributes? true
filter expr(inventories.store_id == parent(inventories.store_id))
end
has_many :stores_alt2, SevenEleven.Store do
This is load test code for above relationships.
store
end
for _ <- 1..3 do
SevenEleven.store_fixture()
end
%{product: product}
end
test "stores", ~M{product} do
assert %{stores: [_, _, _]} = Ashex.load!(product, [:stores])
assert_raise Ecto.Query.CompileError, fn ->
Ashex.load!(product, [:stores_alt1])
end
assert_raise Ecto.Query.CompileError, fn ->
Ashex.load!(product, [:stores_alt2])
end
end
I think three stores
, stores_alt1
, stores_alt2
relationships should be equivalent.
But, only the stores
relationship works,
and other two relationships raise Ecto.Query.CompileError
.
I’m confused how to write relationship with no_attributes? true
.
Is there any proper way to write this kind of relationships correctly? @zachdaniel
What are the details of the error? Just knowing Ecto.Query.CompileError
is not really useful without more information.
With that said, could you also describe specifically what the stores
relationship is meant to provide?
I can’t really give advice as I don’t know what you’re specifically looking to do.
Here are the stacktraces.
stacktrace for stores_alt1
1) test relationships stores (SonetLib.SevenEleven.ProductTest)
test/sonet_lib/seven_eleven/product_test.exs:24
** (Ecto.Query.CompileError) only one distinct expression is allowed in query
code: Ashex.load!(product, [:stores_alt1])
stacktrace:
(ash_postgres 2.4.11) lib/data_layer.ex:1102: AshPostgres.DataLayer.lateral_join_query/3
(ash_postgres 2.4.11) lib/data_layer.ex:961: AshPostgres.DataLayer.run_query_with_lateral_join/4
(ash 3.4.35) lib/ash/actions/read/read.ex:2650: Ash.Actions.Read.run_query/4
(ash 3.4.35) lib/ash/actions/read/read.ex:542: anonymous fn/8 in Ash.Actions.Read.do_read/5
(ash 3.4.35) lib/ash/actions/read/read.ex:886: Ash.Actions.Read.maybe_in_transaction/3
(ash 3.4.35) lib/ash/actions/read/read.ex:269: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:80: Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/relationships.ex:413: anonymous fn/2 in Ash.Actions.Read.Relationships.do_fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:65: Ash.Actions.Read.Relationships.fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:24: Ash.Actions.Read.Relationships.load/4
(ash 3.4.35) lib/ash/actions/read/read.ex:298: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash.ex:1859: Ash.load/3
(ash 3.4.35) lib/ash.ex:1813: Ash.load/3
(ash 3.4.35) lib/ash.ex:1754: Ash.load!/3
test/sonet_lib/seven_eleven/product_test.exs:28: (test)
stacktrace for stores_alt2
1) test relationships stores (SonetLib.SevenEleven.ProductTest)
test/sonet_lib/seven_eleven/product_test.exs:24
** (Ecto.Query.CompileError) only one distinct expression is allowed in query
code: Ashex.load!(product, [:stores_alt2])
stacktrace:
(ash_postgres 2.4.11) lib/data_layer.ex:1102: AshPostgres.DataLayer.lateral_join_query/3
(ash_postgres 2.4.11) lib/data_layer.ex:961: AshPostgres.DataLayer.run_query_with_lateral_join/4
(ash 3.4.35) lib/ash/actions/read/read.ex:2650: Ash.Actions.Read.run_query/4
(ash 3.4.35) lib/ash/actions/read/read.ex:542: anonymous fn/8 in Ash.Actions.Read.do_read/5
(ash 3.4.35) lib/ash/actions/read/read.ex:886: Ash.Actions.Read.maybe_in_transaction/3
(ash 3.4.35) lib/ash/actions/read/read.ex:269: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:80: Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/relationships.ex:413: anonymous fn/2 in Ash.Actions.Read.Relationships.do_fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:65: Ash.Actions.Read.Relationships.fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:24: Ash.Actions.Read.Relationships.load/4
(ash 3.4.35) lib/ash/actions/read/read.ex:298: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash.ex:1859: Ash.load/3
(ash 3.4.35) lib/ash.ex:1813: Ash.load/3
(ash 3.4.35) lib/ash.ex:1754: Ash.load!/3
test/sonet_lib/seven_eleven/product_test.exs:32: (test)
I will explain more about my question.
There are three resources: Store
, Inventory
, Product
.
Store and Product is simple resource, and Inventory is join table resource.
Store
has_many :inventories
Product
has_many :inventories
Inventory
belongs_to :store
belongs_to :product
I know there is many_to_many
feature,
but I wanted to show you there are some hard things when using no_attributes? true
.
A private project in our company uses no_attributes? true
a lot
(There are some scenarios our company have, only no_attributes? true
can be a solution.),
and I meet this kind of error a lot.
How can I avoid these errors and write correct relationship?
Or is this an bug?
** (Ecto.Query.CompileError) only one distinct expression is allowed in query
is a bug.
Please open a bug report.
If you can, please provide a reproduction and as much detail as you can. Ideally a test I can run that reproduces the specific error
I opened a bug report about this.
opened 12:27AM - 28 Oct 24 UTC
bug
needs review
**Describe the bug**
When using `no_attributes? true` in relationships, I encou… nter `Ecto.Query.CompileError` frequently.
There are three resources.
- Store
has_many :inventories
- Product
has_many :inventories
- Inventory (join table resource)
belongs_to :store
belongs_to :product
- relationship code in Product
```
defmodule SonetLib.SevenEleven.Product do
relationships do
has_many :stores, SevenEleven.Store do
no_attributes? true
filter expr(inventories.product_id == parent(id))
end
has_many :stores_alt1, SevenEleven.Store do
no_attributes? true
filter expr(inventories.store_id == parent(inventories.store_id))
end
has_many :stores_alt2, SevenEleven.Store do
no_attributes? true
filter expr(id == parent(inventories.store_id))
end
end
end
```
I think these three relationships are equivalent, but only the first one works.
And the other two relationships raise error when loading them.
- stacktrace
```
1) test relationships stores (SonetLib.SevenEleven.ProductTest)
test/sonet_lib/seven_eleven/product_test.exs:24
** (Ecto.Query.CompileError) only one distinct expression is allowed in query
code: Ashex.load!(product, [:stores_alt1])
stacktrace:
(ash_postgres 2.4.11) lib/data_layer.ex:1102: AshPostgres.DataLayer.lateral_join_query/3
(ash_postgres 2.4.11) lib/data_layer.ex:961: AshPostgres.DataLayer.run_query_with_lateral_join/4
(ash 3.4.35) lib/ash/actions/read/read.ex:2650: Ash.Actions.Read.run_query/4
(ash 3.4.35) lib/ash/actions/read/read.ex:542: anonymous fn/8 in Ash.Actions.Read.do_read/5
(ash 3.4.35) lib/ash/actions/read/read.ex:886: Ash.Actions.Read.maybe_in_transaction/3
(ash 3.4.35) lib/ash/actions/read/read.ex:269: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:80: Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash/actions/read/relationships.ex:413: anonymous fn/2 in Ash.Actions.Read.Relationships.do_fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:65: Ash.Actions.Read.Relationships.fetch_related_records/4
(ash 3.4.35) lib/ash/actions/read/relationships.ex:24: Ash.Actions.Read.Relationships.load/4
(ash 3.4.35) lib/ash/actions/read/read.ex:298: Ash.Actions.Read.do_run/3
(ash 3.4.35) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 3.4.35) lib/ash.ex:1859: Ash.load/3
(ash 3.4.35) lib/ash.ex:1813: Ash.load/3
(ash 3.4.35) lib/ash.ex:1754: Ash.load!/3
test/sonet_lib/seven_eleven/product_test.exs:28: (test)
```
**To Reproduce**
I will attach some links to my public repo.
You can reproduce it easily with test code.
1. resource `Store`
https://github.com/rapidfsub/sonet/blob/develop/test/support/lib/sonet_lib/seven_eleven/store.ex
2. resource `Product`
https://github.com/rapidfsub/sonet/blob/develop/test/support/lib/sonet_lib/seven_eleven/product.ex
3. resource `Inventory` (join table resource for `Store` and `Product`)
https://github.com/rapidfsub/sonet/blob/develop/test/support/lib/sonet_lib/seven_eleven/inventory.ex
4. test code for reproduction
https://github.com/rapidfsub/sonet/blob/develop/test/sonet_lib/seven_eleven/product_test.exs#L24
I know I can use `many_to_many` feature in this example,
but I need a simple example to show the bug in `no_attributes? true` feature.
**Expected behavior**
- relationships works without any error
**Runtime**
- Elixir version
1.17.0-otp-27
- Erlang version
27.0
- OS
mac os sequoia
- Ash version
3.4.35
- any related extension versions
ash_postgres 2.4.11
**Additional context**
I wrote a question about this in elixir forum below.
https://elixirforum.com/t/how-to-write-relationships-with-no-attributes/67042
Thank you, I’ll take a look in the next day or two.
This is fixed in main
of ash_postgres
. I will release new versions of ash
and ash_postgres
this week.
2 Likes
The bug I reported is fixed, but I found another one related to original one.
I opened a new issue in ash_postgres.
opened 11:38PM - 28 Oct 24 UTC
bug
needs review
**Describe the bug**
This issue is fixed.
https://github.com/ash-project/ash_p… ostgres/issues/412
But still a bug is remaining.
When I use the relationship in filter expr, a RuntimeError occurs.
The three read actions below should be equivalent, I think.
But, only `list_by_store_id` works, and `list_by_store_id_alt1`, `list_by_store_id_alt2` don't work and raise error.
- actions in resource
```
defmodule SonetLib.SevenEleven.Product do
actions do
defaults [:read, create: :*]
read :list_by_store_id do
argument :store_id, :string, allow_nil?: false
filter expr(stores.id == ^arg(:store_id))
end
read :list_by_store_id_alt1 do
argument :store_id, :string, allow_nil?: false
filter expr(stores_alt1.id == ^arg(:store_id))
end
read :list_by_store_id_alt2 do
argument :store_id, :string, allow_nil?: false
filter expr(stores_alt2.id == ^arg(:store_id))
end
update :purchase
end
end
```
- stacktrace
```
1) test relationships stores (SonetLib.SevenEleven.ProductTest)
test/sonet_lib/seven_eleven/product_test.exs:25
** (RuntimeError) Error while building reference: inventories.store_id
stacktrace:
(ash_sql 0.2.37) lib/expr.ex:1796: AshSql.Expr.default_dynamic_expr/6
(ash_sql 0.2.37) lib/expr.ex:909: AshSql.Expr.default_dynamic_expr/6
(ash_sql 0.2.37) lib/filter.ex:37: anonymous fn/2 in AshSql.Filter.add_filter_expression/2
(elixir 1.17.0) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
(ash_postgres 2.4.11) lib/data_layer.ex:2998: AshPostgres.DataLayer.filter/4
(ash 3.4.36) lib/ash/query/query.ex:3106: Ash.Query.maybe_filter/3
(ash 3.4.36) lib/ash/query/query.ex:2977: Ash.Query.data_layer_query/2
(ash_sql 0.2.37) lib/join.ex:439: AshSql.Join.related_query/3
(ash_sql 0.2.37) lib/join.ex:345: AshSql.Join.related_subquery/3
(ash_sql 0.2.37) lib/join.ex:873: AshSql.Join.join_relationship/8
(ash_sql 0.2.37) lib/join.ex:136: anonymous fn/10 in AshSql.Join.join_all_relationships/10
(elixir 1.17.0) lib/enum.ex:4858: Enumerable.List.reduce/3
(elixir 1.17.0) lib/enum.ex:2585: Enum.reduce_while/3
(ash_postgres 2.4.11) lib/data_layer.ex:2991: AshPostgres.DataLayer.filter/4
(ash 3.4.36) lib/ash/query/query.ex:3106: Ash.Query.maybe_filter/3
(ash 3.4.36) lib/ash/query/query.ex:2977: Ash.Query.data_layer_query/2
(ash 3.4.36) lib/ash/actions/read/read.ex:544: anonymous fn/8 in Ash.Actions.Read.do_read/5
(ash 3.4.36) lib/ash/actions/read/read.ex:890: Ash.Actions.Read.maybe_in_transaction/3
(ash 3.4.36) lib/ash/actions/read/read.ex:273: Ash.Actions.Read.do_run/3
(ash 3.4.36) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
```
**To Reproduce**
This is the test code to reproduce in my public repo.
https://github.com/rapidfsub/sonet/blob/develop/test/sonet_lib/seven_eleven/product_test.exs#L25
**Expected behavior**
No error raises, when using relationship in expr.
** Runtime
- Elixir version
1.17.0-otp-27
- Erlang version
27.0
- OS
mac os sequoia
- Ash version
git ref ee9415e7bff74210c1e4c3395dc619318a8eee47
- any related extension versions
ash_postgres git ref 0e336d56e1091beec15d6f9173f5067e0a0f9271
**Additional context**
Add any other context about the problem here.