django-pghistory icon indicating copy to clipboard operation
django-pghistory copied to clipboard

Events queryset fails for custom model PKs

Open lokhman opened this issue 9 months ago • 0 comments

If a tracked model has a custom private key field, which has a different database representation to the instance value, the queryset for pghistory.models.Event fails:

Example error:

django.db.utils.DataError: invalid input syntax for type uuid: "acc-uHsnqvKUT9SsDb6xe8i2zi"
LINE 62:               WHERE _event.pgh_obj_id = 'acc-uHsnqvKUT9SsDb6...

This happens because of the bug in EventsQueryCompiler._get_where_clause, which uses PK values directly stringified in:

        if isinstance(rows, models.QuerySet) or len(rows) > 1:
            opt = "IN"
            # TODO: Use a subquery
            pks = "','".join(f"{o.pk}" for o in rows)
            pks = f"('{pks}')"       # <--- here
        else:
            opt = "="
            pks = f"'{rows[0].pk}'"  # <--- and here

Both o.pk and rows[0].pk values should be compiled correctly with tracked_model._meta.pk.get_db_prep_value. Also, it's safe to mogrify the value.

For example, for rows[0].pk the code should be this:

with self.connection.cursor() as cursor:
    value = rows[0]._meta.pk.get_db_prep_value(rows[0].pk, self.connection)
    pks = cursor.mogrify("%s", [value]).decode("utf-8")

lokhman avatar May 08 '24 22:05 lokhman