From 42a9e342ef57a9ffa5016f4f57da633a811d2c0f Mon Sep 17 00:00:00 2001 From: stvn <stvn@mit.edu> Date: Wed, 24 Feb 2021 12:00:34 -0800 Subject: [PATCH] fix: Manually backfill config_id UUIDs again The previous backfills handled NULL entries; this handles empty strings. The difficulty here was that since the empty string in an invalid UUID (as opposed to None/NULL which is just "blank"), attempts to instantiate models would fail, given the invalid data. This meant we couldn't use the Django ORM to handle the migration entirely; we need to craft some raw SQL to work-around these checks and limitations. --- .../0009_backfill-empty-string-config-id.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 lti_consumer/migrations/0009_backfill-empty-string-config-id.py diff --git a/lti_consumer/migrations/0009_backfill-empty-string-config-id.py b/lti_consumer/migrations/0009_backfill-empty-string-config-id.py new file mode 100644 index 0000000..30f6a9e --- /dev/null +++ b/lti_consumer/migrations/0009_backfill-empty-string-config-id.py @@ -0,0 +1,72 @@ +""" +Backfill empty config_id records + +We need to do this with raw SQL, +otherwise the model fails upon instantiation, +as the empty string is an invalid UUID. +""" +import uuid + +from django.db import connection +from django.db import migrations + + +sql_forward = """\ +UPDATE + lti_consumer_lticonfiguration +SET + config_id = %s +WHERE + id = %s +;\ +""" + +sql_select_empty = """\ +SELECT + id +FROM + lti_consumer_lticonfiguration +WHERE + config_id = "" +;\ +""" + + +def _get_ids_with_empty_uuid(): + """ + Retrieve the list of primary keys for each entry with a blank config_id + """ + with connection.cursor() as cursor: + cursor.execute(sql_select_empty) + for row in cursor.fetchall(): + yield row[0] + + +def _create_config_ids(apps, schema_editor): + """ + Generate a UUID for rows missing one + + Note: The model stores these without hyphens. + """ + for _id in _get_ids_with_empty_uuid(): + config_id = uuid.uuid4() + config_id = str(config_id) + config_id = config_id.replace('-', '') + schema_editor.execute(sql_forward, [ + config_id, + _id, + ]) + + +class Migration(migrations.Migration): + """ + Backfill empty config_id records + """ + + dependencies = [ + ('lti_consumer', '0008_fix_uuid_backfill'), + ] + + operations = [ + migrations.RunPython(_create_config_ids, atomic=False), + ] -- GitLab