Skip to content

Commit

Permalink
convert python code into SQL query
Browse files Browse the repository at this point in the history
Run migration as SQL query to optimize performance when number of records huge
  • Loading branch information
kelvin-muchiri committed May 20, 2024
1 parent 07ebcb7 commit e77e6ef
Showing 1 changed file with 4 additions and 37 deletions.
41 changes: 4 additions & 37 deletions onadata/apps/logger/migrations/0014_populate_attachment_xform.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,15 @@
from django.db import migrations


def populate_attachment_xform(apps, schema_editor):
"""Populate xform field for Attachments"""
Attachment = apps.get_model("logger", "Attachment")
queryset = Attachment.objects.filter(xform__isnull=True).values(
"pk", "instance__xform", "instance__user"
)
count = queryset.count()
print("Start populating attachment xform...")
print(f"Found {count} records")

for attachment in queryset.iterator(chunk_size=100):
# We do not want to trigger Model.save or any signal
# Queryset.update is a workaround to achieve this.
# Model.save and the post/pre signals may contain
# some side-effects which we are not interested in
Attachment.objects.filter(pk=attachment["pk"]).update(
xform=attachment["instance__xform"],
user=attachment["instance__user"],
)
count -= 1
print(f"{count} remaining")

print("Done populating attachment xform!")


def reverse_populate_attachment_xform(apps, schema_editor):
"""Reverse populate xform field when migrations are unapplied"""
Attachment = apps.get_model("logger", "Attachment")
queryset = Attachment.objects.filter(xform__isnull=False).values("pk")

for attachment in queryset.iterator(chunk_size=100):
Attachment.objects.filter(pk=attachment["pk"]).update(xform=None, user=None)


class Migration(migrations.Migration):

dependencies = [
("logger", "0013_add_xform_to_logger_attachment"),
]

operations = [
migrations.RunPython(
populate_attachment_xform, reverse_populate_attachment_xform
)
migrations.RunSQL(
sql="WITH logger_attachment_instance AS (SELECT logger_attachment.id, logger_instance.xform_id, logger_instance.user_id FROM logger_attachment INNER JOIN logger_instance ON logger_attachment.instance_id = logger_instance.id INNER JOIN logger_xform T4 ON logger_instance.xform_id = T4.id WHERE logger_attachment.xform_id IS NULL AND T4.deleted_at IS NULL) UPDATE logger_attachment SET xform_id = logger_attachment_instance.xform_id, user_id = logger_attachment_instance.user_id FROM logger_attachment_instance WHERE logger_attachment.id = logger_attachment_instance.id;",
reverse_sql="WITH logger_attachment_instance AS (SELECT logger_attachment.id FROM logger_attachment INNER JOIN logger_xform T4 ON logger_instance.xform_id = T4.id WHERE logger_attachment.xform_id IS NOT NULL AND T4.deleted_at IS NULL) UPDATE logger_attachment SET xform_id = NULL, user_id = NULL FROM logger_attachment_instance WHERE logger_attachment.id = logger_attachment_instance.id;",
),
]

0 comments on commit e77e6ef

Please sign in to comment.