Files
upstream-zulip/zerver/migrations/0794_alter_directmessagegroup_recipient_and_more.py
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

109 lines
3.9 KiB
Python

import django.db.models.deletion
from django.db import connection, migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.utils import names_digest
from django.db.migrations.state import StateApps
from psycopg2.sql import SQL, Identifier
from zerver.lib.partial import partial
def add_unique_and_remove_non_unique_index(
table_name: str,
apps: StateApps,
schema_editor: BaseDatabaseSchemaEditor,
) -> None:
with connection.cursor() as cursor:
constraints = connection.introspection.get_constraints(cursor, table_name)
unique_constraint_name = (
f"{table_name}_recipient_id_{names_digest(table_name, 'recipient_id', length=8)}_uniq"
)
existing = constraints.get(unique_constraint_name)
if existing is None:
# Create unique index concurrently (non-blocking).
cursor.execute(
SQL("CREATE UNIQUE INDEX CONCURRENTLY {name} ON {table} (recipient_id)").format(
table=Identifier(table_name),
name=Identifier(unique_constraint_name),
)
)
# Promote to a table constraint (instant metadata operation).
cursor.execute(
SQL("ALTER TABLE {table} ADD CONSTRAINT {name} UNIQUE USING INDEX {name}").format(
table=Identifier(table_name),
name=Identifier(unique_constraint_name),
)
)
elif existing.get("index"):
# Index was created but not yet promoted (crash between steps).
cursor.execute(
SQL("ALTER TABLE {table} ADD CONSTRAINT {name} UNIQUE USING INDEX {name}").format(
table=Identifier(table_name),
name=Identifier(unique_constraint_name),
)
)
for name, info in constraints.items():
if info["columns"] != ["recipient_id"]:
continue
if info["unique"]:
continue
if not info.get("index"):
continue
cursor.execute(
SQL("DROP INDEX CONCURRENTLY IF EXISTS {name}").format(
name=Identifier(name),
)
)
class Migration(migrations.Migration):
atomic = False
dependencies = [
("zerver", "0793_alter_directmessagegroup_huddle_hash_and_more"),
]
operations = [
# Prevent the naive plan of dropping and re-creating the
# foreign key constraint, and create the unique constraint
# before dropping the non-unique index.
migrations.SeparateDatabaseAndState(
database_operations=[
migrations.RunPython(
partial(
add_unique_and_remove_non_unique_index,
"zerver_huddle",
),
),
migrations.RunPython(
partial(
add_unique_and_remove_non_unique_index,
"zerver_stream",
),
),
],
state_operations=[
migrations.AlterField(
model_name="directmessagegroup",
name="recipient",
field=models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="zerver.recipient",
),
),
migrations.AlterField(
model_name="stream",
name="recipient",
field=models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="zerver.recipient",
),
),
],
),
]