如何修复SQLAlchemy:SAWarning:对表的DELETE语句应删除1行;0个被匹配

mar*_*and 5 python postgresql sqlalchemy flask flask-sqlalchemy

我正在使用SQLAlchemy和PostgreSQL构建带有定向图数据模型的Python Flask应用。我在设置删除级联时遇到问题。尽管经过初步检查似乎可以删除,但是我不确定是否可能以我不理解的方式破坏事物,因为我收到以下警告:

SAWarning: DELETE statement on table 'edges' expected to delete 1 row(s); 0 were matched.  
Please set confirm_deleted_rows=False within the mapper configuration to prevent this warning.  (table.description, expected,rows_matched)
Run Code Online (Sandbox Code Playgroud)

这是我的数据模型的核心。

class Node(db.Model):
    __tablename__ = 'nodes'

    __mapper_args__ = {
        'polymorphic_on': type,
        'polymorphic_identity': 'node'
    }

    id = Column(BigInteger, primary_key=True)
    type = Column(String)

    in_edges = relationship("Edge", cascade="save-update, merge, delete", foreign_keys="Edge.dest", back_populates='dest_node')
    out_edges = relationship("Edge", cascade="save-update, merge, delete", foreign_keys="Edge.src", back_populates='src_node')


class Edge(db.Model):
    __tablename__ = 'edges'

    __mapper_args__ = {
        'polymorphic_on': type,
        'polymorphic_identity': 'edge'
    }

    type = Column(String, primary_key="True")

    src = Column(Integer, ForeignKey('nodes.id'), primary_key=True)
    dest = Column(Integer, ForeignKey('nodes.id'), primary_key=True)

    src_node = relationship("Node", foreign_keys=[src], back_populates='out_edges')
    dest_node = relationship("Node", foreign_keys=[dest], back_populates='in_edges')
Run Code Online (Sandbox Code Playgroud)

节点通过Edge定向连接。边缘将src节点连接到dest节点。要注意的一件事是,节点的主键为id,而边缘的主键为typesrc且为复合主键dest。由于无法将src或dest设置为NULL的Edge,因此,如果删除了Node,则也必须删除以任何方式引用它的所有Edge。

在该模型中,我relationships在Node和Edge上创建了相互填充的SQLAlchemy 。在节点一侧,我可以访问传入和传出的边缘,并且边缘可以访问其连接的节点。

我想做的是删除图形的子集。为此,我通过从节点开始并遍历节点的out_edges来遍历图。我只是明确删除节点。我依靠在两个节点的关系上配置的级联删除来删除边缘。

如图所示进行配置时,我似乎总是会收到警告,这似乎表明未删除某些内容。但是,如果删除节点的in_edges上的级联删除,则警告消失。

我认为可能发生的事情是,由于边缘必须同时存在两个节点,所以当我删除src节点时,它会删除传出的边缘,然后当我删除这些边缘的目标节点时,它会寻找传入的边缘,但是它已经存在已被删除。

因此,删除级联可解决警告并在某些情况下有效,但是有时我要删除一个节点,该节点的传入Edge的src节点不是我正在行走的节点。因此,确保两个关系都导致删除级联是至关重要的,因此我不认为以这种方式抑制警告是正确的做法。

谁能解释发生了什么事?这是可以忽略的安全吗?我做错了吗?

ter*_*yon 5

我认为你的问题是相关的https://bitbucket.org/zzzeek/sqlalchemy/issues/2403/work-around-mysql-innodb-bug-need-per

你可以试试这个代码。

class Edge(db.Model):
    __tablename__ = 'edges'

    __mapper_args__ = {
        'polymorphic_on': type,
        'polymorphic_identity': 'edge',
        'confirm_deleted_rows': False
    }
Run Code Online (Sandbox Code Playgroud)