5

Is there a constraint or some other PostgreSQL feature that prevents CIDR columns from having values that overlap?

For example:

192.168.1.0/24 and 192.168.1.1/32

These could not exist together because 192.168.1.1/32 is contained in the 192.168.1.0/24 subnet.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
Edmond
  • 615
  • 1
  • 5
  • 15

1 Answers1

7

Yes, that is easily done with an exclusion constraint.

CREATE TABLE networks (
   id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
   net cidr NOT NULL
);

ALTER TABLE networks ADD EXCLUDE USING gist (net inet_ops WITH &&);

INSERT INTO networks (net) VALUES ('192.168.1.0/24');
INSERT 0 1

INSERT INTO networks (net) VALUES ('192.168.1.1/32');
ERROR:  conflicting key value violates exclusion constraint "networks_net_excl"
DETAIL:  Key (net)=(192.168.1.1) conflicts with existing key (net)=(192.168.1.0/24).

The exclusion constraint will cause an error whenever you try to insert two rows where the values for net overlap (&& is the "overlaps" operator).

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • Is it possible to limit the constraint based on the value of another field? E.g. I would like to validate that CIDRs do not overlap for a specific VLAN but they can overlap between different vlans. Thank you – mhristache Apr 11 '22 at 09:44
  • 1
    @mhristache Sure, just add the other column to the exclusion constraint. You may need the `btree_gist` extension to use `=` in an exclusion constraint. – Laurenz Albe Apr 11 '22 at 09:57
  • it'd be amazing if you could explain what is going on here. – Rami Aug 25 '23 at 02:33
  • 1
    @Rami I have added an explanation. – Laurenz Albe Aug 26 '23 at 11:28