Skip to content

Conversation

@timvantongeren
Copy link

@timvantongeren timvantongeren commented Apr 4, 2024

This PR adds a hash function to models which contain a primary key relation.
We know that a primary key does indeed offer a unique identifier for the row, and a concat of the primary key fields can thus be used to create a unique string identifying the row.

A use case for this would be the following.
Consider a select on the join of 2 tables, A and B.
In the resulting sequence of tuples, multiple instances of a row of either A or B can be present, as they match multiple times on their counterpart.

The most pythonic way to then retrieve the unique instances / rows of either A or B in the result set would be as follows.

# Retrieving the joined tuples, where A and B have 1 to many relationships.
statement = select(A, B).join(B, A.id == B.id)
result: Sequence[tuple[A,B]] = session.exec(statement).all()

# Unique instances of A
unique_a: list[A] = list(set([a for a, b in result]))

# Unique instances of B
unique_b: list[B] = list(set([b for a, b in result]))

This is currently not possible as the SQLModel class, and the underlying pydantic BaseModel are unhashable.
However, I propose that a SQLModel with properly defined primary keys IS actually hashable, as the primary key defines a unique, hashable property.
This would be in line with the underlying database, as some hash is ofcourse also used in the backend to identify this uniqueness.

@tiangolo
Copy link
Member

Thanks for the interest!

I think this could have some potential problems in some use cases, for example, I think it currently doesn't have in mind the table, if two tables have the same columns, they would conflict.

Also there were two tables with the same columns in two different DBs, and they all had to interact in the same code, they would have conflicts as well.

For now, I would prefer to keep it as is. Although for your use cases you could create a base model with your custom __hash__ and inherit from it. ☕

@tiangolo tiangolo closed this Apr 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants