Opened 2 hours ago

Closed 67 minutes ago

Last modified 16 minutes ago

#36792 closed New feature (duplicate)

Add support for virtual generated columns (PostgreSQL 18+) in GeneratedField

Reported by: Paolo Melchiorre Owned by:
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: postgresql
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Background

PostgreSQL 18 introduces virtual generated columns: columns declared with
GENERATED ALWAYS AS ( <generation_expr> ) VIRTUAL are computed at query time
and do not occupy storage. PostgreSQL 18 also makes VIRTUAL the default for
generated columns while continuing to support STORED (materialized) generated
columns. See the PostgreSQL 18 release notes: PostgreSQL 18 release notes.

Motivation

Django's GeneratedField support currently targets databases that support STORED
(materialized) generated columns. With PostgreSQL 18, users should be able to
declare GeneratedFields that are VIRTUAL (computed at query time) and have
Django generate the correct DDL and perform correct introspection and
migration autogeneration.

Goals

  • Add support in Django's PostgreSQL backend to emit the VIRTUAL keyword in CREATE TABLE and ALTER TABLE statements for generated columns when targeting PostgreSQL 18 or newer.
  • Extend PostgreSQL introspection to detect whether an existing generated column is STORED or VIRTUAL and populate migration state accordingly so autogeneration can produce correct AddField / AlterField operations.
  • Ensure migration operations handle switching between STORED and VIRTUAL where supported by the server, and emit clear errors or warnings when not supported by the connected server version.
  • Add tests and documentation; skip/guard tests on PostgreSQL servers older than 18.

Implementation notes and suggestions

  • Server gating: use the existing server_version_int checks (treat PostgreSQL 18 as the cutoff, e.g. 180000) so that DDL including VIRTUAL is only emitted on servers that support it.
  • DDL generation: update the PostgreSQL schema editor (schema creation/alter) to emit either "VIRTUAL" or "STORED" based on field metadata and server version. If the field model exposes a stored boolean, emit STORED when True and VIRTUAL when False (and server >= 18).
  • Introspection: extend postgresql introspection to read the generation expression and the storage type (stored vs virtual) from information_schema and/or pg_catalog and expose those details in the field_info consumed by the migration autogenerator.
  • Migrations: ensure AlterField and AddField include the storage attribute and that migration autogeneration treats changes in stored/virtual as schema changes. If the connected server does not support VIRTUAL, raise a clear error during migration planning/execution.
  • Tests: add backend tests that:
    • create a model with a GeneratedField stored=True (STORED) and stored=False (VIRTUAL),
    • introspect an existing table with VIRTUAL columns,
    • autogenerate migrations for switching between STORED and VIRTUAL,
    • ensure tests are skipped on PostgreSQL < 18.
  • Documentation: update GeneratedField docs to describe the stored vs virtual option and PostgreSQL version requirements (PG 18+ for VIRTUAL). Recommend keeping DB versions consistent across environments.

Examples

SQL (PG18+):

CREATE TABLE example (
    a integer,
    b integer GENERATED ALWAYS AS (a + 1) VIRTUAL
);

Stored column:

CREATE TABLE example (
    a integer,
    b integer GENERATED ALWAYS AS (a + 1) STORED
);

Django (draft API):

class MyModel(models.Model):
    width = models.IntegerField()
    area = models.GeneratedField(models.F('width') * 2, stored=False)  # VIRTUAL on PG18+

Backward-compatibility and migration considerations

  • Emit VIRTUAL only when connected to PG 18+; otherwise use STORED or raise a clear error.
  • Autogenerated migrations created on PG18 that include VIRTUAL should be documented or guarded to avoid failures on older servers.
  • Recommend teams keep DB versions consistent across dev/test/prod if they plan to use VIRTUAL columns.

Change History (2)

comment:1 by David Sanders, 67 minutes ago

Resolution: duplicate
Status: newclosed

Hi Paolo 👋

Was previously raised by Adam, it just missed out on the 6.0 release however 😭

Duplicate of #36277

comment:2 by Paolo Melchiorre, 16 minutes ago

I totally missed it :)
Thanks

Note: See TracTickets for help on using tickets.
Back to Top