-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add support for JSONB subscripting introduced in Postgresql 14 #10927
Comments
Hi, You are mentioning postgresql but the example is using sqlite. |
Sorry, you can reproduce it with: from sqlalchemy import Column, MetaData, Table, create_engine
from sqlalchemy.dialects.sqlite import base as sqlite
engine = create_engine("sqlite://")
metadata = MetaData()
with engine.connect() as connection:
sqlite_json = Table("json_test", metadata, Column("foo", sqlite.JSON))
metadata.create_all(connection)
value = {"json": {"foo": "bar"}}
connection.execute(sqlite_json.insert(), dict(foo=value))
connection.execute(
sqlite_json.update().values({sqlite_json.c.foo["otherjson"]: sqlite_json.c.foo["json"]})
) It fails for Postgres too. |
But they are you using |
For Postgres, I has able to use sqlite_json.update().values({sqlite_json.c.foo: sa.func.jsonb_set(sqlite_json.c.foo, '{"otherjson"}', sqlite_json.c.foo["json"])}) Works for me now, but I think the performance is not the same of writing only an attribute to the column. |
I'm using proper |
Using postgresql json seems to work as expected. import sqlalchemy as sa
from sqlalchemy.dialects import postgresql as pg
t = sa.table('foo', sa.column('bar', pg.JSON))
u = t.update().values({t.c.bar['foo']: t.c.bar['src']})
print(u.compile(dialect=pg.dialect()).string) this prints a string that looks fine
|
This SQL fails on Postgres 16 (at least for JSONB). I think it should be UPDATE foo SET bar[%(bar_1)s]=(foo.bar -> %(bar_2)s) |
Ok I though you wanted to generate something like Your proposed syntax will error too using json:
|
Here the SQL statements, ran in Postgres 16: => create table foo (
id integer primary key,
bar jsonb not null default '{}'::jsonb
);
CREATE TABLE
=> update foo set bar -> 'a' = bar -> 'b';
ERROR: syntax error at or near "->"
LINE 1: update foo set bar -> 'a' = bar -> 'b';
^
=> update foo set bar['a'] = bar -> 'b';
UPDATE 0 |
Transformed this in to an use case, since it's not something that's currently implemented. Do you know if the |
I think for -- it works
update foo set bar['a'] = bar['b']; For normal create table foo
(
id integer primary key,
bar json not null default '{}'::json
);
insert into foo values (1, '{"foo": "bar"}');
=> select bar['foo'] from foo;
ERROR: cannot subscript type json because it does not support subscripting |
If so then 2.1 could maybe use this syntax in place of the current one for jsonb types. @zzzeek do you have other ideas? |
assuming I am seeing what's needed here, we only need the new syntax for the left hand side in an UPDATE SET clause, and on prior versions of PostgreSQL, nothing is supported anyway. if that's all accurate then I'd seek to get the postgresql compiler to use this new syntax only for left hand side SET variables. |
Any particular reason for not changing it in all cases, other than the current way works fine? |
I like to keep changes minimal and backend agnostic if possible |
JSONB exists from Postgres 12, but JSONB subscripting is documented from Postgres 14, probably doesn't work before that. https://www.postgresql.org/docs/14/datatype-json.html#JSONB-SUBSCRIPTING Needs some research to understand the details. Changing all cases may be problematic. |
there is likely already infrastructure in the compiler to support doing special compilation for the "keys" of update.values(). pretty sure MySQL has something happening on that end. |
Ok. I'll update the initial issue and target 2.0 |
Add support for the subscript jsonb notation introduced in pg 14. Ref at https://www.postgresql.org/docs/current/datatype-json.html#JSONB-SUBSCRIPTING.
This notation seems to be allowed in more placed than the classical "arrow" notation.
For example it can be used in a set clause of an updated:
I'm not sure if this should become the preferred syntax in postgresql 14+.This new syntax is used initially only by in the update set clause, since it would be not strange to have different syntax depending on json/jsonb. May be revisited in the future
Original text below
Describe the bug
I don't know if it is an intentional unsupported feature or a bug.
I'm trying to copy a value from a key to another key and it fails on Postgres.
For Postgres 16, the SQL generated is:
The update fails with:
The expected syntax is
UPDATE table SET column['foo']=column -> 'bar'
.Optional link from https://docs.sqlalchemy.org which documents the behavior that is expected
No response
SQLAlchemy Version in Use
2.0.21
DBAPI (i.e. the database driver)
psycopg2
Database Vendor and Major Version
PostgreSQL 16
Python Version
3.11
Operating system
Linux
To Reproduce
Error
Additional context
No response
The text was updated successfully, but these errors were encountered: