Больше, чем для поля IP-адреса INET в PostgreSQL версии > 9

Итак, я написал свой собственный поиск для поля PostgreSQL INET в моем приложении DRF, так как Django не поддерживает эти специфические поля PostgreSQL. Я использую собственное поле IP в своих объектах для поддержки собственных поисков.

Все мои работы по поиску находят, кроме этих двух:

class HostGreaterOrEqual(Lookup):
    """ Lookup to check if an IP address is greater than or equal. Used for net ranges"""
    lookup_name = "host_greater_or_equal"

    def as_sql(self, qn, connection):
        lhs, lhs_params = self.process_lhs(qn, connection)
        rhs, rhs_params = self.process_rhs(qn, connection)
        params = lhs_params + rhs_params
        return "%s >= %s" % (lhs, rhs), params
    
class HostLessOrEqual(Lookup):
    """ Lookup to check if an IP address is less than or equal. Used for net ranges"""
    lookup_name = "host_less_or_equal"

    def as_sql(self, qn, connection):
        lhs, lhs_params = self.process_lhs(qn, connection)
        rhs, rhs_params = self.process_rhs(qn, connection)
        params = lhs_params + rhs_params
        return "%s <= %s" % (lhs, rhs), params

В моей модели есть поле address и address_end для хранения диапазонов IP-адресов. Я хотел использовать вышеупомянутый поиск для создания соответствующих запросов, например, таких:

items = queryset.filter(
                Q(address__host_greater_or_equal=value)
                & Q(address_end__host_less_or_equal=value)
            )

В документации к PostgreSQL версии 9 я вижу операторы "меньше или равно" и "больше или равно". Но если я проверю документацию для Version 15, кажется, что они были удалены.

Была ли эта функциональность просто удалена или есть что-то похожее, чего я еще не нашел?

Из v13.0 release notes:

Переформатировать таблицы, содержащие информацию о функциях и операторах для большей ясности (Том Лейн)

Так что с тех пор они не находятся на своем обычном месте в документации, но они все еще доступны.

select inet '192.168.1.5' <  inet '192.168.1.6' as "less than",
       inet '192.168.1.5' >  inet '192.168.1.6' as "greater than",
       inet '192.168.1.5' <= inet '192.168.1.6' as "less than or equal",
       inet '192.168.1.5' >= inet '192.168.1.6' as "greater than or equal";
-- less than | greater than | less than or equal | greater than or equal
-------------+--------------+--------------------+-----------------------
-- t         | f            | t                  | f

show server_version;
--          server_version
-------------------------------------
-- 15rc2 (Debian 15~rc2-1.pgdg110+1)

Который вы можете протестировать на разных версиях здесь: online demo.


Вы всегда можете проверить системные таблицы, чтобы убедиться, что действительно доступно

select * 
from pg_catalog.pg_operator 
where oprname in ('<=','>=') 
and oprcode::text ilike '%network%';
-- oid  | oprname | oprnamespace | oprowner | oprkind | oprcanmerge | oprcanhash | oprleft | oprright | oprresult | oprcom | oprnegate |  oprcode   |   oprrest   |     oprjoin
--------+---------+--------------+----------+---------+-------------+------------+---------+----------+-----------+--------+-----------+------------+-------------+-----------------
-- 1204 | <=      |           11 |       10 | b       | f           | f          |     869 |      869 |        16 |   1206 |      1205 | network_le | scalarlesel | scalarlejoinsel
-- 1206 | >=      |           11 |       10 | b       | f           | f          |     869 |      869 |        16 |   1204 |      1203 | network_ge | scalargesel | scalargejoinsel

Или посмотрите их в psql с \do+

\do+ <= inet inet
--                                         List of operators
--   Schema   | Name | Left arg type | Right arg type | Result type |  Function  |    Description
--------------+------+---------------+----------------+-------------+------------+--------------------
-- pg_catalog | <=   | inet          | inet           | boolean     | network_le | less than or equal

\do+ >= inet inet
--                                           List of operators
--   Schema   | Name | Left arg type | Right arg type | Result type |  Function  |      Description
--------------+------+---------------+----------------+-------------+------------+-----------------------
-- pg_catalog | >=   | inet          | inet           | boolean     | network_ge | greater than or equal

psql -E показывает \do+ находит его с помощью следующего запроса, который вы можете выполнить в другом клиенте.

SELECT n.nspname as "Schema",
  o.oprname AS "Name",
  CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS "Left arg type",
  CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS "Right arg type",
  pg_catalog.format_type(o.oprresult, NULL) AS "Result type",
  o.oprcode AS "Function",
  coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),
           pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS "Description"
FROM pg_catalog.pg_operator o
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace
     LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprleft
     LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace
     LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = o.oprright
     LEFT JOIN pg_catalog.pg_namespace nt1 ON nt1.oid = t1.typnamespace
WHERE o.oprname OPERATOR(pg_catalog.~) '^(>=)$' COLLATE pg_catalog.default
  AND pg_catalog.pg_operator_is_visible(o.oid)
  AND (t0.typname OPERATOR(pg_catalog.~) '^(inet)$' COLLATE pg_catalog.default
        OR pg_catalog.format_type(t0.oid, NULL) OPERATOR(pg_catalog.~) '^(inet)$' COLLATE pg_catalog.default)
  AND pg_catalog.pg_type_is_visible(t0.oid)
  AND (t1.typname OPERATOR(pg_catalog.~) '^(inet)$' COLLATE pg_catalog.default
        OR pg_catalog.format_type(t1.oid, NULL) OPERATOR(pg_catalog.~) '^(inet)$' COLLATE pg_catalog.default)
  AND pg_catalog.pg_type_is_visible(t1.oid)
ORDER BY 1, 2, 3, 4;
Вернуться на верх