You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Issue with parameters in relation to in and a dynamic/1 collection #164
val=dynamic(^["abc","def"])cond=dynamic([a],a.colin^val)query=fromain"table",where: ^cond,select: a.col{sql,x}=Repo.to_sql(:all,query)# sql = SELECT t0."col" FROM "table" AS t0 WHERE (t0."col" IN (?,?))# x = [["abc", "def"]]
Works:
cond=dynamic([a],a.colin^["abc","def"])query=fromain"table",where: ^cond,select: a.col{sql,x}=Repo.to_sql(:all,query)# sql = SELECT t0."col" FROM "table" AS t0 WHERE (t0."col" IN (?,?))# x = ["abc", "def"]
Looks like there's some place flattening out the parameters, which doesn't catch the dynamic case
Postgres uses the array as parameter because it's also doing ANY($1). The sqlite query uses multiple parameters (?, ?), so flattening the list into the top level parameters makes sense.
I am curious, why is that being used rather than just passing the list directly?
This is for a query builder, where conditions come from a datastructure. The right hand side of in could also be another expr instead of a value, hence the separation.
I do not believe this can be supported. The list of array values without changing things upstream in ecto. All of the other SQL implementations can handle it just fine because ANY(?) is supported, but we do not have access to it in sqlite and we also do not have the ability to flatten that param list before being passed to the query preparation state. Unsure on how to raise a more helpful exception stating that this can not be supported. I don't want to break a dynamic built condition from being used.
So the work around for now is to not use dynamic in this way.
For some more background why this happens. The nested dynamic does not "see" the outer dynamic. So it doesn't know it's part of an in expression. The in expression is handled specially by the Ecto planner to split it up, which is why not nesting the dynamics works.
So this could theoretically be supported of we can make inner dynamics see the context they are in. But I imagine this is not a simple change.
Activity
warmwaffles commentedon Apr 18, 2025
I'll look into this soon.
warmwaffles commentedon Apr 24, 2025
Indeed @LostKobrakai this looks to be a bug. Working on a fix now.
warmwaffles commentedon Apr 24, 2025
@LostKobrakai the "works" is different behavior than the postgres adapter because the
ANYkeyword doesn't appear.I'll need to figure something out here.
LostKobrakai commentedon Apr 24, 2025
Postgres uses the array as parameter because it's also doing
ANY($1). The sqlite query uses multiple parameters(?, ?), so flattening the list into the top level parameters makes sense.warmwaffles commentedon Apr 24, 2025
Yea we can't use the
[["ABC", "DEF"]]construct because sqlite has no ability to bind a list of values. https://sqlite.org/c3ref/bind_blob.htmlThis may require upstream changes in Ecto. I'm still trying to figure out a solution. As a work around, don't do this:
I am curious, why is that being used rather than just passing the list directly?
LostKobrakai commentedon Apr 25, 2025
This is for a query builder, where conditions come from a datastructure. The right hand side of
incould also be another expr instead of a value, hence the separation.warmwaffles commentedon Apr 25, 2025
I do not believe this can be supported. The list of array values without changing things upstream in ecto. All of the other SQL implementations can handle it just fine because
ANY(?)is supported, but we do not have access to it in sqlite and we also do not have the ability to flatten that param list before being passed to the query preparation state. Unsure on how to raise a more helpful exception stating that this can not be supported. I don't want to break a dynamic built condition from being used.So the work around for now is to not use dynamic in this way.
greg-rychlewski commentedon May 10, 2025
For some more background why this happens. The nested dynamic does not "see" the outer dynamic. So it doesn't know it's part of an
inexpression. Theinexpression is handled specially by the Ecto planner to split it up, which is why not nesting the dynamics works.So this could theoretically be supported of we can make inner dynamics see the context they are in. But I imagine this is not a simple change.