Ecto change @schema_prefix on a join statement

hi

i am creating a query to the database, i am using ecto, and it change the @schema_prefix of my module ex:

defmodule NA.DB.Schema.Detail do
  use Ecto.Schema
  @schema_prefix "schema1"

  schema "table" do
    field :id, :integer
    field :master_id, :integer
   end
end

the another module:

defmodule NA.DB.Schema.Master do
  use Ecto.Schema
  
  @schema_prefix "schema2"
  @primary_key false
  
  schema "patient_eligibility_list" do
    field :item_id, :integer
    field :parent_id, :integer
    field :num, :integer
  end
end

the query:

from p in Patient,
      join: pel in Master,
      join: group in Detail,
      where: group.id == pel.group_id, 
      select: %{item_id: pel.item_id, parent_id: pel.parent_id, group_num: group.group_num}   

and it change the schema of the detail to the schema from the master and it throw a error that a table doesn’t exist.

2 Likes

Due to a conscious design decision by the Ecto team Ecto does not allow cross-schema joins for reasons of things that I’ve never seen in real-life at any of the corporations that I’ve worked for in the past 2 decades but I am completely sure is used ā€˜out in the wild’ (just I really do not think that the case is that common based on my life experience). So right now, ā€œNot Possible with Ectoā€. :frowning:

For elaboration, it is designed for the purpose of being able to change the schema of an ā€˜entire’ query for separating, say, user websites by schema name. I can see that use case being useful, I’ve just never seen it done myself, and the fact that you can do @schema_name on a schema does not seem to fit that model at all so I do not know why @schema_name exists at all then (you’d think if you are not overriding the schema name on a query that the default @schema_name should be used instead yes? But it is not, it is completely and entirely ignored unless it is in the from). What I usually see in every business I’ve ever worked (mostly oracle DB’s) is that they separated schemas based on ā€˜purpose’, so all user related data would be in one schema, say for a school then all course data would be in another schema (foreign-linking back to the user schema) and so forth…

I tried to suggest once to default to the @schema_name if the schema was not otherwise specified, but it was very very quickly and loudly denied, thus completely making this use-case impossible with the ecto queries (I still do not understand why, if anyone wanted to unify all the schemas then they could leave @schema_name off and/or override the schema names in the repo function directly as you already can…).

What are the current best workarounds for this limitation in Ecto?

Define a sql view in a common schema that does the join?

Use Ecto schemaless queries?

Either of those two work. I don’t like the schemaless bit as it does not fit in my model of stuff well (and I’ve not tried it honestly, I just dumped down into raw SQL…), and view’s I try to minimize (unless I’m making a materialized view or so) in case I am forced into the Oracle database itself from PostgreSQL (where I’d not be allowed to create a view)… >.>

i was using another post to resolve it:

Yep, that is the raw sql way, and yeah it loses the type information so you have to re-type everything manually, which sucks when there are 40+ columns. ^.^;