Opened 3 hours ago

#36981 new New feature

Add PostgreSQL num_nonnulls (code provided)

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

Description

I recently implemented "anyOf" / "tagged union" fields. I added specialized CheckConstraints using num_nonnulls

The code looks like this:

class NumNonNulls(Func):
    """
    Wraps PostgreSQL `num_nonnulls`.

    Returns the number of non-null arguments as an integer.  Can be used with
    `F()` references to model fields (including e.g. OneToOne) relationships.

    Example::

        NumNonNulls(F("one_to_one_rel_1"), F("one_to_one_rel_1"))
        ->  SQL: num_nonnulls("one_to_one_rel_1_id", "one_to_one_rel_2_id")
    """

    function = "num_nonnulls"

    def __init__(self, *expressions: object, **extra) -> None:
        super().__init__(*expressions, output_field=IntegerField(), **extra)


class NumNonNullsEq(Func):
    """
    Renders ``num_nonnulls(<args>) = <n>`` as a boolean expression.

    Suitable for use as the `condition` of a `CheckConstraint`.

    Parameters
    ----------
    *expressions:
        The expressions (e.g. `F()` expressions) to pass to `num_nonnulls`.
    count:
        The value or expression the result must equal.

    Example::

        NumNonNullsEq(F("one_to_one_rel_1"), F("one_to_one_rel_2"), count=1)
        -> SQL: num_nonnulls("one_to_one_rel_1_id", "one_to_one_rel_2_id") = 1
    """

    arg_joiner = " = "
    template = "%(expressions)s"

    def __init__(self, *expressions: object, count: object, **extra) -> None:
        if not expressions:
            raise ValueError("NumNonNullsEq() requires at least one expression.")

        super().__init__(
            NumNonNulls(*expressions),
            count,
            output_field=BooleanField(),
        )

Is there any interest from Django's side in this?

Change History (0)

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