Больше, чем для поля 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, кажется, что они были удалены.
Была ли эта функциональность просто удалена или есть что-то похожее, чего я еще не нашел?
Переформатировать таблицы, содержащие информацию о функциях и операторах для большей ясности (Том Лейн)
Так что с тех пор они не находятся на своем обычном месте в документации, но они все еще доступны.
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;