[Django] #33607: `PostgresIndex` uses `suffix` for both index name and method

11 views
Skip to first unread message

Django

unread,
Mar 30, 2022, 6:23:15 AM3/30/22
to django-...@googlegroups.com
#33607: `PostgresIndex` uses `suffix` for both index name and method
------------------------------------------------+------------------------
Reporter: Alexandru Mărășteanu | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: dev
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------------+------------------------
`django.contrib.postgres.indexes.PostgresIndex` uses the `suffix`
attribute for both generating the index name (in
`Index.set_name_with_model` see
https://github.com/django/django/blob/fac662f4798f7e4e0ed9be6b4fb4a87a80810a68/django/db/models/indexes.py#L153-L186)
and for deciding the indexing method (in `PostgresIndex.create_sql` i.e.
`CREATE INDEX ... USING {suffix} ...` see
https://github.com/django/django/blob/fac662f4798f7e4e0ed9be6b4fb4a87a80810a68/django/contrib/postgres/indexes.py#L25-L36).
A developer using and extending `PostgresIndex` for use with multiple
opclasses is unable to specify a custom suffix for the naming scheme.

For example, given two custom indexes like:


{{{
class Foo(GinIndex):
def __init__(self, *args, **kwargs):
super().__init__(*args, opclasses=[some opclass], **kwargs)


class Bar(GinIndex):
def __init__(self, *args, **kwargs):
super().__init__(*args, opclasses=[some opclass], **kwargs)
}}}


If set on the same model fields, both `Foo.set_name_with_model` and
`Bar.set_name_with_model` would then generate the same index name à la
`dbtable_field_hash_gin` which is not ok because index names need to be
unique.

Setting custom `suffix`es on `Foo` and `Bar` is not possible with the
current code because `PostgresIndex.create_sql` uses the suffix as the
index method. If the suffix doesn't match any of the supported opclasses,
then PostgreSQL complains about it.

To workaround that, an option would be to override the `create_sql`
method:

{{{
class Foo(GinIndex):
suffix = "foo"

def __init__(self, *args, **kwargs):
super().__init__(*args, opclasses=[some opclass], **kwargs)

def create_sql(self, model, schema_editor, using="", **kwargs):
return super().create_sql(model, schema_editor, using="gin",
**kwargs)


class Bar(GinIndex):
suffix = "bar"

def __init__(self, *args, **kwargs):
super().__init__(*args, opclasses=[some opclass], **kwargs)

def create_sql(self, model, schema_editor, using="", **kwargs):
return super().create_sql(model, schema_editor, using="gin",
**kwargs)
}}}

The problem is, even though `PostgresIndex.create_sql` accepts a `using`
argument, it currently ignores it. From the source code:

{{{
class PostgresIndex(Index):
...

def create_sql(self, model, schema_editor, using="", **kwargs):
...
statement = super().create_sql(
model, schema_editor, using=" USING %s" % self.suffix,
**kwargs
)
...
}}}

So in the end there's no way to extend the `PostgresIndex` with a custom
suffix. I was able to do it by temporarily setting a custom suffix in
`set_name_with_model` but that's more of a hack rather than a solution.

--

That said, I believe there are two things which need to be addressed here:

1. Distinguish between the index name suffix and the index method

`PostgresIndex` would then declare another property which indicated the
method to use when defining the index i.e. `using`.

2. `PostgresIndex.create_sql` respects the `using` argument

E.g. (also considering point 1 above):

{{{
class PostgresIndex(Index):
...

def create_sql(self, model, schema_editor, using="", **kwargs):
...
statement = super().create_sql(
model, schema_editor, using=using or self.using, **kwargs
)
...
}}}

---

If this is accepted, I'm available to work on it.

--
Ticket URL: <https://code.djangoproject.com/ticket/33607>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 30, 2022, 6:26:21 AM3/30/22
to django-...@googlegroups.com
#33607: `PostgresIndex` uses `suffix` for both index name and method
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: (none)
Mărășteanu |

Type: Bug | Status: new
Component: contrib.postgres | Version: dev
Severity: Normal | Resolution:

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Alexandru Mărășteanu):

Note I'm aware that the index class requires an explicit name when using
opclasses, but I think if these were addressed, then it would be easier in
the future to leave the name generation to Django.

--
Ticket URL: <https://code.djangoproject.com/ticket/33607#comment:1>

Reply all
Reply to author
Forward
0 new messages