Session.merge_all() does not suppress autoflush during merge cascade, unlike Session.merge()
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
- #13716 @Huang-404-Q による — マージされずにクローズ
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 74/100
調査の方向性
lib/sqlalchemy/orm/session.py:4154 の Session.merge_all() から始め、その動作を Session.merge() および提示された再現例と比較してください。リレーションシップの解決時に autoflush を発生させる merge cascade の回帰テストを追加してください。テストで merge_all() が部分的な状態の flush を回避することを確認し、再現例が IntegrityError なしで成功すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Session.merge_all() runs its merges outside Session.no_autoflush, while Session.merge() wraps the same _merge call in with self.no_autoflush. When a relationship cascade needs to lazy-load a detached target, the resulting autoflush inserts a half-merged, not-yet-complete object and can violate constraints.
from sqlalchemy import Column, ForeignKey, Integer, String, create_engine, select
from sqlalchemy.orm import DeclarativeBase, Session, relationship
class Base(DeclarativeBase):
pass
class Parent(Base):
__tablename__ = "parent"
id = Column(Integer, primary_key=True)
class Child(Base):
__tablename__ = "child"
id = Column(Integer, primary_key=True)
parent_id = Column(ForeignKey("parent.id"), nullable=False)
name = Column(String, nullable=False)
parent = relationship(Parent)
engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
with Session(engine) as session:
session.add(Parent(id=1))
session.commit()
with Session(engine) as session:
parent = session.get(Parent, 1)
with Session(engine) as session:
child = Child(name="c", parent=parent)
child.parent_id = None
session.merge_all([child]) # IntegrityError: NOT NULL constraint failed: child.parent_id
session.commit()
session.merge(child) in the same position succeeds because it uses no_autoflush.
Expected: merge_all() behaves like merge() and does not flush partially merged state while resolving the relationship. Actual: autoflush emits INSERT INTO child (parent_id, name) VALUES (NULL, NULL) and raises IntegrityError.
Likely cause: Session.merge_all at lib/sqlalchemy/orm/session.py:4154 lacks the with self.no_autoflush: block used by merge().
I have a regression test and a one-line fix ready.
- 主要言語
- Python
- スター
- 12.3k
- フォーク
- 1.8k
- 平均マージ
- 1日 2時間
- マージ済み PR(30日)
- 5
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
sqlalchemy/sqlalchemy のほかの issue
-
bug orm regression
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
sqlalchemy/sqlalchemy#13718 · コメント 8 件 ·
メンテナーはふだん 1 日以内に返信
-
Inspect overloads for Any handle raiseerr wrong対応中かも @princejain756 が 5 日前に担当しました。 オープンcode review in progress typing
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
sqlalchemy/sqlalchemy#13704 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
-
Document that asyncpg error messages no longer include DETAIL in 2.1対応中かも @artem-sitd が 17 日前に担当しました。 オープン
難易度 1/5 1〜3時間 初心者へのやさしさ 82/100
sqlalchemy/sqlalchemy#13655 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
TableValueType should accept is_ operator class再び着手できるかも @nightcityblade が 20 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンpostgresql sql use case
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
sqlalchemy/sqlalchemy#13651 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
PostgreSQL multihost URL with bracketed IPv6 hosts raises ValueError: too many values to unpack再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンbug engine postgresql
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
sqlalchemy/sqlalchemy#13637 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
sqlalchemy/sqlalchemy の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
nansencenter/geodataset#39 ·
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
awslabs/visual-asset-management-system#804 ·
メンテナーはふだん 1 日以内に返信
-
follow-up
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
link-rot
難易度 1/5 1時間未満 初心者へのやさしさ 67/100