-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
reduce JSON operator precedence to 5 and add tests #9836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi, thanks for reporting. Example: import sqlalchemy as sa
from sqlalchemy.dialects import postgresql as PG
t = sa.table("t", sa.column("a", sa.Integer), sa.column("b", PG.JSONB))
any_ = sa.any_(sa.values(t.c.a).data([(1,), (2,), (3,)]).scalar_values())
q = t.c.a == any_
print(q.compile(dialect=PG.dialect()))
q2 = t.c.b.contains(any_)
print(q2.compile(dialect=PG.dialect())) this prints
|
I wonder why the parenthesis dont work? how is PG parsing this that the parens are confusing it? usually PG is the DB where we dont have to worry about silly things like this |
So here is the patch to remove the parens: diff --git a/lib/sqlalchemy/dialects/postgresql/json.py b/lib/sqlalchemy/dialects/postgresql/json.py
index 232f058042..41ad983a71 100644
--- a/lib/sqlalchemy/dialects/postgresql/json.py
+++ b/lib/sqlalchemy/dialects/postgresql/json.py
@@ -16,7 +16,7 @@ from ...sql import operators
__all__ = ("JSON", "JSONB")
-idx_precedence = operators._PRECEDENCE[operators.json_getitem_op]
+idx_precedence = 5
ASTEXT = operators.custom_op(
"->>", That's one way at least, this sets precedence at 5 which is what CONTAINS has for PG ARRAY, not sure why JSON is different. but the test case still fails (desired SQL though) can we get something that works? or is this another issue?
|
don't need the cast. just use literal with a type: async def main():
engine_string = "postgresql+asyncpg://scott:tiger@localhost:5432/postgres"
engine = create_async_engine(engine_string, echo=True)
async with engine.begin() as conn:
await conn.run_sync(meta.create_all)
async with engine.connect() as conn:
stmt = select(t1).filter(
t1.c.jsonb_data.contains(
any_(
array(
[
literal([{"foo": ii}], JSONB)
for ii in ["bar", "baz"]
]
),
)
)
)
await conn.execute(stmt)
await engine.dispose() |
any_()
with contains()
on a Postgres JSONB column
output SQL is:
|
this is somewhat connected to #9041 |
Federico Caselli has proposed a fix for this issue in the main branch: Improve PostgreSQL custom operators https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/4636 |
Describe the bug
I'm trying to query for rows where a JSONB column contains any of an array of JSON values. The raw SQL query I wrote works (cribbing from this post), and looks like this:
which I translated into SQLA as
However, that produces the following SQL, which results in a syntax error:
It seems the extra parentheses break the query.
Optional link from https://docs.sqlalchemy.org which documents the behavior that is expected
No response
SQLAlchemy Version in Use
2.0.15
DBAPI (i.e. the database driver)
asyncpg==0.27.0
Database Vendor and Major Version
PostgreSQL 15.2
Python Version
3.10
Operating system
Linux
To Reproduce
Error
Additional context
No response
The text was updated successfully, but these errors were encountered: