HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Postgres inet array contains a single ip

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
inetpostgresarraysinglecontains

Problem

Requirement: user can add single ips or ip address ranges to a database table(for example permissions table having ipAddresses of inet[] type). I need to query that a single ip is contained in the array of ipAddresses field which can be array of ip addresses or ip address ranges or both. I have tried to add where query like this:

WHERE "ipAddresses" @> '192.168.1.5'::inet


and also like this

WHERE "ipAddresses" >> '192.168.1.5'::inet


but no luck.
Thanks in advance.

id          uuid      NOT NULL  gen_random_uuid()
permissions uuid[]      
ipAddresses inet[]      
createdAt   timestamp with time zone        now()
updatedAt   timestamp with time zone        now()


source: pg array functions and
pg network address functions

Solution

While McNets's solutions would also work, it's possibly the easiest to use ANY with an operator, in this case equality:

SELECT '10.10.10.10' = ANY ('{10.10.10.10, 10.10.10.20}'::inet[]);


The background is that an inet array is no different from any other array type in this regard - ANY will work with any boolean-returning operator that is defined on the base type.

The above applies to equality of single IP addresses. If you need to match a single IP against a range, you'll need the <<= operator instead of =:

SELECT '10.10.10.10'::inet <<= ANY ('{10.10.10.10, 10.10.10.20}'::inet[]);

 ?column? 
──────────
 t

SELECT '10.10.10.10'::inet <<= ANY ('{10.10.10.0/28, 10.10.10.20}'::inet[]);

 ?column? 
──────────
 t


In your case, the solution would look like

WHERE '192.168.1.5' <<= ANY ("ipAddresses")


The performance of this can be poor for the lack of really efficient indexing. To address this, see the suggestion in McNets's answer.

Code Snippets

SELECT '10.10.10.10' = ANY ('{10.10.10.10, 10.10.10.20}'::inet[]);
SELECT '10.10.10.10'::inet <<= ANY ('{10.10.10.10, 10.10.10.20}'::inet[]);

 ?column? 
──────────
 t

SELECT '10.10.10.10'::inet <<= ANY ('{10.10.10.0/28, 10.10.10.20}'::inet[]);

 ?column? 
──────────
 t
WHERE '192.168.1.5' <<= ANY ("ipAddresses")

Context

StackExchange Database Administrators Q#180419, answer score: 7

Revisions (0)

No revisions yet.