> And if you need real SQL intervals, Django pushes you towards raw expressions or `Func()` wrappers.
It's possible to use a very similar construct to SQL Alchemy here by using the `Now` [function](https://docs.djangoproject.com/en/6.0/ref/models/database-fu...) (it uses `STATEMENT_TIMESTAMP` which is likely more correct than `NOW()` here alternatively there is `TransactionNow`) by doing `Now() - timedelta(days=30)`.
Virtual generated columns are not required to allow an index to be used in this case without incurring the cost of materializing `to_tsvector('english', message)`. Postgres supports indexing expressions and the query planner is smart enough to identify candidate on exact matches.
You are correct, I missed that. In MySQL, functional indices are implemented as invisible generated virtual columns (and there is no vector index type supported yet that I'm aware of), but Postgres has a more capable approach.
It doesn't make the article less interesting but this statement is wrong most of the time
> This scenario is essentially identical to one in which there's a single migration statement that requires an `AccessExclusiveLock` and performs a table rewrite, such as adding a NOT NULL column with a DEFAULT value.
Unless the `DEFAULT` value is `VOLATILE` (this is rarely the case as usually default values are at least `STABLE`) no table rewrite is necessary since Postgres 11.
> Many other useful performance improvements, including the ability to avoid a table rewrite for ALTER TABLE ... ADD COLUMN with a non-null column default
Thanks, I will fix this part. As far as I can tell, it is only the example of what can cause the table rewrite that's wrong, so it would be correct if the example was to make a varchar shorter? Although I guess that's not a table rewrite, only a long validation...
>“Roughly” because Django ORM doesn’t support the JSONB `?` operator.
The `has_key` [lookup](https://docs.djangoproject.com/en/6.0/topics/db/queries/#has...) does exactly that.
> And if you need real SQL intervals, Django pushes you towards raw expressions or `Func()` wrappers.
It's possible to use a very similar construct to SQL Alchemy here by using the `Now` [function](https://docs.djangoproject.com/en/6.0/ref/models/database-fu...) (it uses `STATEMENT_TIMESTAMP` which is likely more correct than `NOW()` here alternatively there is `TransactionNow`) by doing `Now() - timedelta(days=30)`.
The result is the following `filter` call
which translates to the following SQL which can be confirmed in [this playground](https://dryorm.xterm.info/hn-47110310)