Skip to content

fix: support StringConstraints metadata in SQLAlchemy type generation#2001

Open
Sujit-1509 wants to merge 2 commits into
fastapi:mainfrom
Sujit-1509:fix/stringconstraints-metadata
Open

fix: support StringConstraints metadata in SQLAlchemy type generation#2001
Sujit-1509 wants to merge 2 commits into
fastapi:mainfrom
Sujit-1509:fix/stringconstraints-metadata

Conversation

@Sujit-1509

Copy link
Copy Markdown

Summary

When using Pydantic v2's StringConstraints inside Annotated, SQLModel correctly applies validation constraints but does not propagate max_length to the generated SQLAlchemy column type.

For example:

from typing import Annotated
from pydantic import StringConstraints

class Item(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: Annotated[str, StringConstraints(max_length=50)]

currently generates a column with no length constraint, even though max_length=50 is declared.

Root Cause

get_field_metadata() recognizes PydanticMetadata and MaxLen metadata objects, but does not recognize StringConstraints, causing the metadata extractor to return FakeMetadata() instead of the constraint object.

As a result, get_sqlalchemy_type() cannot read max_length and falls back to an unconstrained string type.

Changes

  • Add support for StringConstraints in get_field_metadata().
  • Add a regression test verifying that Annotated[str, StringConstraints(max_length=50)] produces a SQLAlchemy column with length == 50.

Testing

Added a regression test that fails on the current implementation and passes with this change.

@YuriiMotov

Copy link
Copy Markdown
Member

@Sujit-1509, do you have specific use case there it's required to use StringConstraints instead of passing max_length via Field?

You marked it as fix, but this is not a fix because it's not documented in SQLMOdel's docs.
To accept this as a feature request we need stronger arguments.
Please, avoid opening PRs just to contribute to the project. We are overloaded with PRs..

@Sujit-1509

Copy link
Copy Markdown
Author

@YuriiMotov Thanks for the feedback.

The use case I had in mind is projects migrating to Pydantic v2 patterns and reusing constrained types across multiple models.

For example:

from typing import Annotated
from pydantic import StringConstraints

Name = Annotated[str, StringConstraints(max_length=50)]

class User(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: Name

In this case validation correctly enforces max_length=50, but the generated SQLAlchemy column does not receive the corresponding length constraint.

My assumption was that this was an inconsistency because SQLModel already extracts length-related metadata to configure SQLAlchemy column types, but currently ignores StringConstraints metadata.

That said, I understand your point that SQLModel's documented approach is Field(max_length=...). If support for StringConstraints is considered a feature request rather than a bug fix, I'm happy to reclassify the PR accordingly or discuss whether this functionality would be useful for users adopting Pydantic v2 style constraints.

@github-actions github-actions Bot removed the waiting label Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants