Skip to content

Commit d67e766

Browse files
authored
[fix] Resolve issues with false tag reassignment (#3344)
1 parent 753f4b1 commit d67e766

6 files changed

Lines changed: 85 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## Unreleased:
4+
5+
### Fixes:
6+
- Fix issues with tag false reassignment (mihran113)
7+
38
## 3.29.1 May 8, 2025:
49

510
### Enhancements:

aim/sdk/data_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
DATA_VERSION = (1, 3)
1+
DATA_VERSION = (1, 4)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""empty message
2+
3+
Revision ID: 661514b12ee1
4+
Revises: 46b89d830ad8
5+
Create Date: 2025-06-05 19:52:31.221392
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from alembic.context import get_context
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '661514b12ee1'
15+
down_revision = '46b89d830ad8'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
21+
def upgrade():
22+
# Get the SQLite connection context
23+
context = get_context()
24+
naming_convention = {
25+
"fk":
26+
"fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
27+
}
28+
# Use batch operations for SQLite
29+
with op.batch_alter_table('run_tag', naming_convention=naming_convention) as batch_op:
30+
# First drop the existing foreign key
31+
batch_op.drop_constraint('fk_run_tag_run_id_run', type_='foreignkey')
32+
batch_op.drop_constraint('fk_run_tag_tag_id_tag', type_='foreignkey')
33+
34+
# Then create a new one with CASCADE
35+
batch_op.create_foreign_key('fk_run_tag_run_id_run', 'run', ['run_id'], ['id'], ondelete='CASCADE')
36+
batch_op.create_foreign_key('fk_run_tag_tag_id_tag', 'tag', ['tag_id'], ['id'], ondelete='CASCADE')
37+
38+
39+
with op.batch_alter_table('note', naming_convention=naming_convention) as batch_op:
40+
# First drop the existing foreign key
41+
batch_op.drop_constraint('fk_note_run_id_run', type_='foreignkey')
42+
43+
# Then create a new one with CASCADE
44+
batch_op.create_foreign_key('fk_note_run_id_run', 'run', ['run_id'], ['id'], ondelete='CASCADE')
45+
46+
47+
def downgrade():
48+
# Use batch operations for SQLite
49+
naming_convention = {
50+
"fk":
51+
"fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
52+
}
53+
# Use batch operations for SQLite
54+
with op.batch_alter_table('run_tag', naming_convention=naming_convention) as batch_op:
55+
# Drop the CASCADE foreign key
56+
batch_op.drop_constraint('fk_run_tag_run_id_run', type_='foreignkey')
57+
batch_op.drop_constraint('fk_run_tag_tag_id_tag', type_='foreignkey')
58+
59+
# Then create a new one with CASCADE
60+
batch_op.create_foreign_key('fk_run_tag_run_id_run', 'run', ['run_id'], ['id'],)
61+
batch_op.create_foreign_key('fk_run_tag_tag_id_tag', 'tag', ['tag_id'], ['id'],)
62+
63+
with op.batch_alter_table('note', naming_convention=naming_convention) as batch_op:
64+
# First drop the existing foreign key
65+
batch_op.drop_constraint('fk_note_run_id_run', type_='foreignkey')
66+
67+
# Then create a new one with CASCADE
68+
batch_op.create_foreign_key('fk_note_run_id_run', 'run', ['run_id'], ['id'],)
69+

aim/storage/structured/db.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
)
1010
from aim.storage.types import SafeNone
1111
from aim.web.configs import AIM_LOG_LEVEL_KEY
12-
from sqlalchemy import create_engine
12+
from sqlalchemy import create_engine, event
1313
from sqlalchemy.orm import scoped_session, sessionmaker
1414

1515

@@ -66,6 +66,7 @@ def __init__(self, path: str, readonly: bool = False):
6666
pool_size=10,
6767
max_overflow=20,
6868
)
69+
event.listen(self.engine, 'connect', lambda c, _: c.execute('pragma foreign_keys=on'))
6970
self.session_cls = scoped_session(sessionmaker(autoflush=False, bind=self.engine))
7071
self._upgraded = None
7172

aim/storage/structured/sql_engine/entities.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,9 @@ def from_hash(cls, runhash: str, created_at, session) -> 'ModelMappedRun':
8787

8888
@classmethod
8989
def delete_run(cls, runhash: str, session) -> bool:
90-
try:
91-
rows_affected = session.query(RunModel).filter(RunModel.hash == runhash).delete()
92-
session_commit_or_flush(session)
93-
except Exception:
94-
return False
90+
rows_affected = session.query(RunModel).filter(RunModel.hash == runhash).delete()
91+
session_commit_or_flush(session)
92+
9593
return rows_affected > 0
9694

9795
@classmethod

aim/storage/structured/sql_engine/models.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def default_to_run_hash(context):
2828
run_tags = Table(
2929
'run_tag',
3030
Base.metadata,
31-
Column('run_id', Integer, ForeignKey('run.id'), primary_key=True, nullable=False),
31+
Column('run_id', Integer, ForeignKey('run.id', ondelete='CASCADE'), primary_key=True, nullable=False),
3232
Column('tag_id', Integer, ForeignKey('tag.id'), primary_key=True, nullable=False),
3333
)
3434

@@ -51,7 +51,9 @@ class Run(Base):
5151
experiment_id = Column(ForeignKey('experiment.id'), nullable=True)
5252

5353
experiment = relationship('Experiment', backref=backref('runs', uselist=True, order_by='Run.created_at.desc()'))
54-
tags = relationship('Tag', secondary=run_tags, backref=backref('runs', uselist=True))
54+
tags = relationship(
55+
'Tag', secondary=run_tags, backref=backref('runs', uselist=True), cascade='all, delete', passive_deletes=True
56+
)
5557
notes = relationship('Note', back_populates='run')
5658

5759
def __init__(self, run_hash, created_at=None):
@@ -106,7 +108,7 @@ class Note(Base):
106108

107109
id = Column(Integer, autoincrement=True, primary_key=True)
108110
content = Column(Text, nullable=False, default='')
109-
run_id = Column(Integer, ForeignKey('run.id'))
111+
run_id = Column(Integer, ForeignKey('run.id', ondelete='CASCADE'),)
110112
experiment_id = Column(Integer, ForeignKey('experiment.id'))
111113

112114
created_at = Column(DateTime, default=datetime.datetime.utcnow)

0 commit comments

Comments
 (0)