Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Session.merge_all() does not suppress autoflush during merge cascade, unlike Session.merge()

Chiusa Adatta ai principianti
#13,715 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

  • #13716 di @Huang-404-Q — chiusa senza merge

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
74/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python, sqlalchemy, sqlite
Ambito
databases

Direzione di ricerca

Parti da Session.merge_all() in lib/sqlalchemy/orm/session.py:4154 e confrontane il comportamento con Session.merge() e con la riproduzione fornita. Aggiungi un test di regressione per il merge cascade che attiva autoflush durante la risoluzione della relazione. Il lavoro è completo quando il test conferma che merge_all() evita di eseguire il flush di uno stato parziale e la riproduzione riesce senza IntegrityError.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.

Lingua principale
Python
Stelle
12.3k
Fork
1.8k
Merge medio
1g 2h
PR unite (30g)
5

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di sqlalchemy/sqlalchemy

Tutte le issue di sqlalchemy/sqlalchemy

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.