OvermindDL1
So I got handed more tables in a different schema from mine that I need to cross-join on. I know Ecto did have this bug last year, does it have it fixed ‘now’ though? Right now the schema_prefix definition on ecto schema seems entirely ignored and it is instead using the wrong schema on the join, still. I just updated Ecto and it still has this bug. How can you work around this bug?
Right now doing something like:
Repo.one(from(s in RemoteDB.S, join: t in Tag, on: t.name==s.last_name, where: s.id==1))
Is giving a query like (abbreviated):
SELECT s0.* FROM "otherschema"."s" AS s0 INNER JOIN "otherschema"."tags" AS t1 ON t1."name" = s0."last_name" WHERE (s0."id" = 1)
Which is of course entirely a wtf and causes it to puke with:
** (Postgrex.Error) ERROR 42P01 (undefined_table): relation "otherschema.tags" does not exist
When the SQL should of course be:
SELECT s0.* FROM "otherschema"."s" AS s0 INNER JOIN "myschema"."tags" AS t1 ON t1."name" = s0."last_name" WHERE (s0."id" = 1)
Which of course works fine from the database directly.
This has suddenly put a right-on stop on my work because of this bug… >.<
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
Hi everyone,
I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding.
I sta...
New
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication):
toke...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
mgwidmann
How would ecto know that
Tagis located within another (database) schema? Ecto Schemas are not in any way tied to the database they are stored in.As far as I know this is not a supported feature. I would +1 this feature however, I’m not sure what that would look like… Perhaps something like
join: t in {MySchema, Tag}?OvermindDL1
Please see: Ecto.Schema — Ecto v3.14.0
Specifically (bolding is my own emphasis):
So yes, it does know, it has the information. ^.^
That is how it is populating the schema as it is, probably is that whatever schema the initial ‘from’ is becomes the schema for all the joins, even when they have their own, specifically the joins are ignoring the
@schema_prefixon all schemas in the join and overriding it with the from’s@schema_prefix. Since I am using thefromsyntax, but it fails on joins, I’m curious if there’s been any movement towards fixing this long-standing bug or if there is any safe work-around that does not involve dropping into raw SQL (or fragments)? I’m entirely halted on integrating these new tables until I drop down to raw SQL statements, which is not as careful for obvious reasons. ^.^;OvermindDL1
Feel free to jump to bottom (I found a fix!), this will mostly be a dump while I troubleshoot. ^.^
It seems the reason the join’s are ignored is that there is a query-wide prefix which is used for all tables referenced, which is definitely not right. ^.^
As can be seen at:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/repo/queryable.ex#L114-L119
The prefix is set if there was a
:prefixoption passed in, which again further overrides the@schema_prefixattribute on a schema. Even ignoring if a:prefixoption is given it still seems to hold the table atoms themselves, so it can still get the schema information, and in fact it does by getting it on the ‘from’ part, but the next thing it calls is execute as per:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/repo/queryable.ex#L35
Then to the Planner where it builds the query for the adapter:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/repo/queryable.ex#L122
So going into the Planner we see it calls
prepareat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L109
Where it then calls
prepare_sourcesat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L216
Which then calls
prepare_joinsat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L231
Which then hits at:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L338
Which then goes to
prepare_sourcevia:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L343
Which does grab the source from it but also leaves the module atom at:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L247
Which then goes all back up and appends all these sources onto the main
sourceslist. So at this point they all should be correct and have the source information grabbed out and all combined properly as can be seen at:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L233
So at this point we go back up to the
prepareand continue does the cache section at:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L218
Which ends up calling
finalize_cacheat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L415
Which seems to cache based on the prefix if a user passed it in at:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L500
Excepting this, we continue back up and down the path to
query_with_cacheat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L114
Which calls the function right below it that calls
build_metain every branch depending on if found in the cache or not at:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L118-L129
So continue to that function to see what it does and we see it grabs the ‘global query prefix’ as well as process the
sourcesviabuild_sources_metaat:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L182
to handle the subqueries and so forth. But it soon gets passed to
adapter.prepare, which ends up calling:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapters/sql.ex#L63
So
@conn.allends up calling into the postgresql adapter as that is what I’m using, where at the top of that function it callscreate_names:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapters/postgres/connection.ex#L120
Which ends up iterating over the list of sources (which is a tuple of
{"table_name", SchemaModule}at:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapters/postgres/connection.ex#L567-L579
And at:
https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapters/postgres/connection.ex#L570-L572
You can clearly see it ignores the module entirely, thus never grabbing the prefix for it, thus completely ignoring their configuration. I changed those lines to be this instead (I.E. I just added this second line is all):
And lo-and-behold, it works! Honestly I’ve no clue why the
:prefixkey is on the query at all, if anything the schema should have the prefix and the prefix could be overridable on a per-schema basis, not globally…But yeah, have to edit my own version of ecto, and it breaks the
:prefixoption on things likeRepo.all(good riddance, schema’s prefix should be overridable, not globally…), but joins actually work now! ^.^OvermindDL1
Sent an Issue request at:
https://github.com/elixir-ecto/ecto/issues/1942
mgwidmann
Well cool! Good to know, I didn’t think this feature existed!
OvermindDL1
I am really really badly needing to join across schemas, like really badly right now, preferably without building up SQL manually as there is a lot of ecto query transformations happening…
Help?
@josevalim @michalmuskala Anyone?
I still do not understand why this limitation exists, the use-cases I’d read make no sense for the generic case that could handle it all…
josevalim
Nothing changed since the issue you opened. Ecto does not allow queries across schemas. And nothing will change until someone writes a proposal that is backwards compatible and puts the work into it.
josevalim
FWIW, you should be able to do:
or at least:
which you can easily encapsulate in a macro. But you do lose the Ecto schema information (although Ecto has many tools to help with that).
OvermindDL1
I’ve actually had to resolve into passing maps around everywhere and anywhere as it is due to extremely dynamic returns from the ancient database, so it works.
However, your example gave me an idea for a macro that I think can work well, hmm…
/me still has never seen anyone in real life use prefix’s for user separation and not as dividing of departments at a place of work or so, which I’ve seen at 4 places to date…