tortoise-orm icon indicating copy to clipboard operation
tortoise-orm copied to clipboard

Change restrictions on Charfield, Textfield

Open gdmoore opened this issue 4 years ago • 2 comments

CharField requires a max_length but not all databases mandate this. In Postgresql, the max_length can be optional. It would be nice to have support for the same functionality. Discussing it with @grigi brought up the idea of allowing max_length to be 0, in which case it will be unbounded if the database supports it.

TextField doesn't support any indexes currently. I think it should allow b-tree indexing. There are many use cases where b-tree index is useful, such as needing to perform prefix matches (textfield__startswith="..."). This is a separate use case from full-text search.

Wherever there are DB-specific implementation differences for Fields, the documentation should make it clear what restriction(s) apply across databases.

gdmoore avatar May 06 '20 12:05 gdmoore

This is a problem for me as well. It's unclear to me whether the "index" or "unique" properties of a field actually affect any logic within Tortoise, other than the schema generation. I've just disabled 'index' in Tortoise but I still have the index created manually in Postgres.

davidpurser avatar Dec 16 '21 14:12 davidpurser

I would kind of label it as a bug, as the following is valid PG syntax

CREATE TABLE IF NOT EXISTS roles
(
    id         UUID      NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
    name       TEXT   NOT NULL UNIQUE,
    realm      TEXT,
    created_at TIMESTAMPTZ NOT NULL             DEFAULT NOW(),
    updated_at TIMESTAMPTZ
);

CREATE INDEX roles_realm_idx ON roles (realm);

and the matching code

class Role(Model):
    id = fields.UUIDField(pk=True)
    name = fields.TextField(unique=True, null=False)
    real = fields.TextField(index=True),
    created_at = fields.DatetimeField(auto_now=True, null=False)
    updated_at = fields.DatetimeField()

fails on name due to the TextField init code either on unique or index

class TextField(Field[str], str):  # type: ignore
    """
    Large Text field.
    """

    indexable = False
    SQL_TYPE = "TEXT"

    def __init__(
        self, pk: bool = False, unique: bool = False, index: bool = False, **kwargs: Any
    ) -> None:
        if pk:
            ...
        if unique:
            # PG TextField DO support unique indexes
            raise ConfigurationError(
                "TextField doesn't support unique indexes, consider CharField or another strategy"
            )
        if index:
            # PG TextField DO support other indexes
            raise ConfigurationError("TextField can't be indexed, consider CharField")

        super().__init__(pk=pk, **kwargs)

failing on unique or index

whisust avatar Feb 18 '24 12:02 whisust