Closed roscom closed 1 year ago
Hey @roscom,
If I replace all the .select
calls with .arel_table.project
calls, it appears to work, eg:
Role.select(Role.arel_table[Arel.star]).where(
Role.arel_table[:id].in(
Domain.arel_table.project(:role_id).where(
Domain.arel_table[:expired_on].eq(nil).and(
Domain.arel_table[:id].in(
DomainPage.arel_table.project(:domain_id).where(
DomainPage.arel_table[:expired_on].eq(nil).and(
DomainPage.arel_table[:id].in(
PageKeyword.arel_table.project(:domain_page_id).where(
PageKeyword.arel_table[:expired_on].eq(nil).and(PageKeyword.arel_table[:active])
)
)
)
)
)
)
)
).and(
Role.arel_table[:role_type_id].eq(2).and(Role.arel_table[:expired_on].eq(nil))
)
)
Well, actually it almost works. Unfortunately it looks like Scuttle doesn't know how to handle IS TRUE
, so you'll have to modify PageKeyword.arel_table[:active]
so it's PageKeyword.arel_table[:active].eq(true)
.
That said, have you considered using joins for this instead of all these nested subqueries? Eg:
SELECT roles.*
FROM roles
JOIN domains
ON domains.role_id = roles.id
AND domains.expired_on IS NULL
JOIN domain_pages
ON domain_pages.domain_id = domains.id
AND domain_pages.expired_on IS NULL
JOIN page_keywords
ON page_keywords.domain_page_id = domain_pages.id
AND page_keywords.expired_on IS NULL
AND page_keywords.active IS TRUE
WHERE roles.role_type_id = 2
AND roles.expired_on IS NULL
which becomes
Role.select(Role.arel_table[Arel.star]).where(
Role.arel_table[:role_type_id].eq(2).and(Role.arel_table[:expired_on].eq(nil))
).joins(
Role.arel_table.join(Domain.arel_table).on(
Domain.arel_table[:role_id].eq(Role.arel_table[:id]).and(Domain.arel_table[:expired_on].eq(nil))
).join_sources
).joins(
Role.arel_table.join(DomainPage.arel_table).on(
DomainPage.arel_table[:domain_id].eq(Domain.arel_table[:id]).and(DomainPage.arel_table[:expired_on].eq(nil))
).join_sources
).joins(
Role.arel_table.join(PageKeyword.arel_table).on(
PageKeyword.arel_table[:domain_page_id].eq(DomainPage.arel_table[:id]).and(
PageKeyword.arel_table[:expired_on].eq(nil).and(PageKeyword.arel_table[:active])
)
).join_sources
)
The following sql is valid and works:
and generates the following arel equivalent in scuttle:
which results in the following nonsense sql when run through the rails console:
I can see this is a rails issue, not scutlle.io.
Reading your comments on nested subqueries, "it is a matter of the right 'incantation'" which I've been experimenting with to no avail.
Would you be able to provide some direction on how to incant this the right way? "#project" does not seem to be useful in this context.
Regards Ross