sqlmodel icon indicating copy to clipboard operation
sqlmodel copied to clipboard

✨ Add support for `Literal` types

Open nsaccente opened this issue 5 months ago • 11 comments

This PR addresses issue 57. The original issue explains that attempting to use a Literal type annotation in a SQLModel raises a type error from issubclass. This is because Literal is not a class, but a typing._SpecialForm, so static funcs like isinstance and issubclass don't work with it.

The fix was pretty straightforward, I just added a check before an isinstance or issubclass would have been called that checks if type_ is Literal.

nsaccente avatar Jul 24 '25 02:07 nsaccente

I have no idea how to add the proper labels to this PR, it looks like the permissions aren't set up to allow me to.

nsaccente avatar Jul 28 '25 13:07 nsaccente

@nsaccente, thanks for working on this! This works, but could you please add a test?

YuriiMotov avatar Aug 05 '25 17:08 YuriiMotov

@nsaccente, thanks for working on this! This works, but could you please add a test?

Sure. I'll try to get that done sometime this week.

nsaccente avatar Aug 06 '25 11:08 nsaccente

I've been fighting with getting the tests to work. I've been able to get things to pass in some versions of python, but not others. Any guidance on how to run these CI tests locally?

nsaccente avatar Aug 16 '25 01:08 nsaccente

📝 Docs preview for commit 545a55aa31fd2b31ffde18ed18932c47c1956145 at: https://4238df7a.sqlmodel.pages.dev

github-actions[bot] avatar Aug 26 '25 14:08 github-actions[bot]

@nsaccente: there were some tricky linting errors that I've now fixed.

@YuriiMotov: do you have time to give this another review?

svlandeg avatar Aug 26 '25 14:08 svlandeg

Here is how I see it: https://github.com/fastapi/sqlmodel/pull/1541 Created that draft PR just to check that tests and linter pass

YuriiMotov avatar Aug 27 '25 09:08 YuriiMotov

@YuriiMotov: you're right - it's more clean overall. I'm happy to defer the Literal import to either another PR or to just wait for 3.8 deprecation, at which point we shouldn't forget to clean this up. Let me clean up this PR, addressing your comments.

svlandeg avatar Aug 27 '25 10:08 svlandeg

Click the button!

nsaccente avatar Sep 01 '25 21:09 nsaccente

I'm seeing that this assumes all Literal values are strings, so a model like this:

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(unique=True)
    weakness: Literal[1, 2, 3]

...would still create the column in the DB as a string, not as an integer. :thinking:

tiangolo avatar Sep 20 '25 16:09 tiangolo

Things are getting complex.. We can easily add special cases for Literal[1, 2, 3] or Literal[True, False] to create column with proper type.

The question is, do we expect any kind of validation for these values? Our database column type is just CHAR or INTEGER, so, database will not enforce the value to be correct against Literal[1, 2, 3] type. If we have the value 42 in database, it can break user's code in a very tricky way one day

YuriiMotov avatar Oct 01 '25 15:10 YuriiMotov