Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Fix downgrading to previous version of Synapse #15907

Merged
merged 2 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/15907.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add foreign key constraint to `event_forward_extremities`.
7 changes: 6 additions & 1 deletion synapse/storage/background_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,14 @@ class ForeignKeyConstraint(Constraint):
Attributes:
referenced_table: The "parent" table name.
columns: The list of mappings of columns from table to referenced table
deferred: Whether to defer checking of the constraint to the end of the
transaction. This is useful for e.g. backwards compatibility where
an older version inserted data in the wrong order.
"""

referenced_table: str
columns: Sequence[Tuple[str, str]]
deferred: bool

def make_check_clause(self, table: str) -> str:
join_clause = " AND ".join(
Expand All @@ -94,7 +98,8 @@ def make_check_clause(self, table: str) -> str:
def make_constraint_clause_postgres(self) -> str:
column1_list = ", ".join(col1 for col1, col2 in self.columns)
column2_list = ", ".join(col2 for col1, col2 in self.columns)
return f"FOREIGN KEY ({column1_list}) REFERENCES {self.referenced_table} ({column2_list})"
defer_clause = " DEFERRABLE INITIALLY DEFERRED" if self.deferred else ""
return f"FOREIGN KEY ({column1_list}) REFERENCES {self.referenced_table} ({column2_list}) {defer_clause}"


@attr.s(auto_attribs=True)
Expand Down
4 changes: 3 additions & 1 deletion synapse/storage/databases/main/event_federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ def __init__(
update_name="event_forward_extremities_event_id_foreign_key_constraint_update",
table="event_forward_extremities",
constraint_name="event_forward_extremities_event_id",
constraint=ForeignKeyConstraint("events", [("event_id", "event_id")]),
constraint=ForeignKeyConstraint(
"events", [("event_id", "event_id")], deferred=True
),
unique_columns=("event_id", "room_id"),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,25 @@
event_id TEXT NOT NULL,
room_id TEXT NOT NULL,
UNIQUE (event_id, room_id),
CONSTRAINT event_forward_extremities_event_id FOREIGN KEY (event_id) REFERENCES events (event_id)
CONSTRAINT event_forward_extremities_event_id FOREIGN KEY (event_id) REFERENCES events (event_id) DEFERRABLE INITIALLY DEFERRED
)
"""


def run_create(cur: LoggingTransaction, database_engine: BaseDatabaseEngine) -> None:
# We mark this as a deferred constraint, as the previous version of Synapse
# inserted the event into the forward extremities *before* the events table.
# By marking as deferred we ensure that downgrading to the previous version
# will continue to work.
run_validate_constraint_and_delete_rows_schema_delta(
cur,
ordering=7803,
update_name="event_forward_extremities_event_id_foreign_key_constraint_update",
table="event_forward_extremities",
constraint_name="event_forward_extremities_event_id",
constraint=ForeignKeyConstraint("events", [("event_id", "event_id")]),
constraint=ForeignKeyConstraint(
"events", [("event_id", "event_id")], deferred=True
),
sqlite_table_name="event_forward_extremities2",
sqlite_table_schema=FORWARD_EXTREMITIES_TABLE_SCHEMA,
)
Expand Down
8 changes: 6 additions & 2 deletions tests/storage/test_background_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,9 @@ def delta(txn: LoggingTransaction) -> None:
update_name="test_bg_update",
table="test_constraint",
constraint_name="test_constraint_name",
constraint=ForeignKeyConstraint("base_table", [("b", "b")]),
constraint=ForeignKeyConstraint(
"base_table", [("b", "b")], deferred=False
),
sqlite_table_name="test_constraint2",
sqlite_table_schema=table2_sqlite,
)
Expand All @@ -604,7 +606,9 @@ def delta(txn: LoggingTransaction) -> None:
"test_bg_update",
table="test_constraint",
constraint_name="test_constraint_name",
constraint=ForeignKeyConstraint("base_table", [("b", "b")]),
constraint=ForeignKeyConstraint(
"base_table", [("b", "b")], deferred=False
),
unique_columns=["a"],
)

Expand Down