Reputation: 21737
I have a table with INET columns and want to run a query filtering all entries which are in any of a set of given networks. For example:
CREATE TABLE foo (
cidr INET
);
In SQL I can write the following:
SELECT cidr FROM foo WHERE cidr <<= ANY '{"192.168.1.0/24", "192.168.3.0/24"}';
I found the "any" operator in SQLAlchemy which works well for standard operators, but cannot get it to work with the <<=
operator. How do I do that?
So I have something like this:
from sqlalchemy.dialects.postgresql import Any
query = session.query(Foo)
query = query.filter(Any(
Foo.cidr,
[ip_network('192.168.1.0/24'), ip_network('192.168.3.0/24')],
operator=? # <-- What do I need to put here?
))
Additionally, the model defines a custom type to adapt the "ip_network" type to the appropriate DB type. This change prevents me from using a text
construct with bound params, so currently I have to resort to string concatenations.
Upvotes: 2
Views: 4286
Reputation: 20538
To solve your immediate problem, you can use custom_op
:
session.query(Foo).filter(Any(
Foo.cidr,
array([cast('192.168.1.0/24', INET), cast('192.168.3.0/24', INET)]),
operator=custom_op("<<="),
))
But dialects.postgresql.Any
is deprecated in favor of sql.expression.any_
, which is more natural to use:
arr = array([cast('192.168.1.0/24', INET), cast('192.168.3.0/24', INET)])
session.query(Foo).filter(Foo.cidr.op("<<=")(any_(arr)))
This renders SQL like this:
SELECT ...
FROM foo
WHERE foo.cidr <<= ANY (ARRAY[CAST(%(param_1)s AS INET), CAST(%(param_2)s AS INET)])
Upvotes: 2