All Products
Search
Document Center

PolarDB:ip4r (network address storage)

Last Updated:Oct 30, 2025

This topic describes the background, data types, and usage of the ip4r extension.

Applicability

The following versions of PolarDB for PostgreSQL (Compatible with Oracle) are supported:

  • Oracle syntax compatibility 2.0 (minor engine version 2.0.14.9.13.0 or later)

  • Oracle syntax compatibility 1.0 (minor engine version 2.0.11.9.36.0 or later)

Note

You can view the minor engine version in the console or by running the SHOW polardb_version; statement. If your minor engine version does not meet the requirements, you must upgrade the minor engine version.

Background information

ip4r is a third-party extension supported by PolarDB for PostgreSQL (Compatible with Oracle) that provides data types for storing IPv4 and IPv6 addresses. Unlike PostgreSQL's built-in network data types such as inet/cidr, ip4r supports index scans for the contains operator >>=. In addition, ip4r has the following features compared to the built-in network data types of PostgreSQL:

  • Clearer semantics: It distinguishes between a network block and a specific IP address within that block.

  • Lower overhead: PostgreSQL uses variable-length data types to support IPv6 data. This creates significant overhead in scenarios where you only need to store IPv4 data. ip4r uses fixed-length data types for single addresses.

Data types

ip4r provides a variety of data types for storing and representing IPv4 or IPv6 data:

Data type

Description

ip4

A single IPv4 address.

ip4r

An arbitrary IPv4 address range.

ip6

A single IPv6 address.

ip6r

An arbitrary IPv6 address range.

ipaddress

A single IPv4 or IPv6 address.

iprange

An arbitrary IPv4 or IPv6 address range.

Single-address data types and type conversions

The following three data types are used to store single IP addresses:

  • ip4: The input must be in the nnn.nnn.nnn.nnn format. The data is stored as a 32-bit unsigned integer.

  • ip6: The input must be in the standard hexadecimal representation of an IPv6 address. The data is stored as two 64-bit values.

  • ipaddress: The input must be in either the ip4 or ip6 format.

ip4r provides type conversions for these three data types. The rules are as follows:

Note

In the following table, ipX represents one of the three data types described above.

Source type

Target type

Format

ipX

text

text(ipX) or ipX::text (explicit)

text

ipX

ipX(text) or text::ipX (explicit)

ipX

cidr

cidr(ipX) or ipX::cidr (assignment)

inet

ipX

ipX(inet) or inet::ipX (assignment)

ipX

numeric

to_numeric(ipX) or ipX::numeric (explicit)

numeric

ipX

ipX(numeric) or bigint::ipX (explicit)

ip4

bigint

to_bigint(ip4) or ip4::bigint (explicit)

bigint

ip4

ip4(bigint) or bigint::ip4 (explicit)

ip4

float8

to_double(ip4) or ip4::float8 (explicit)

float8

ip4

ip4(float8) or float8::ip4 (explicit)

ipX

varbit

to_bit(ipX) or ipX::varbit (explicit)

bit(32)

ip4

ip4(bit) or bit::ip4 (explicit)

bit(128)

ip6

ip6(bit) or bit::ip6 (explicit)

varbit

ipX

ipX(varbit) or varbit::ipX (explicit)

ipX

bytea

to_bytea(ipX) or ipX::bytea (explicit)

bytea

ipX

ipX(bytea) or bytea::ipX (explicit)

ipX

ipXr

ipXr(ipX) or ipX::ipXr (implicit)

ip4

ipaddress

ipaddress(ip4) or ip4::ipaddress (implicit)

ip6

ipaddress

ipaddress(ip6) or ip6::ipaddress (implicit)

ipaddress

ip4

ip4(ipaddress) or ipaddress::ip4 (assignment)

ipaddress

ip6

ip6(ipaddress) or ipaddress::ip6 (assignment)

Address-range data types and type conversions

The following three data types are used to store IP address ranges:

  • ip4r: Stores an IPv4 address range. For example, 192.0.2.100-192.0.2.200. 192.0.2.0/24 is equivalent to 192.0.2.0-192.0.2.255.

  • ip6r: Stores an IPv6 address range. For example, 2001::1234-2001::2000:0000. 2001::/112 is equivalent to 2001::-2001::ffff.

  • iprange: The input must be in either the ip4r or ip6r format.

ip4r provides type conversions for these three data types. The rules are as follows:

Note

In the following table, ipXr represents one of the three data types described above.

Source type

Target type

Format

ipX

ipXr

ipXr(ipX) or ipX::ipXr (implicit)

ipXr

text

text(ipXr) or ipXr::text (explicit)

text

ipXr

ipXr(text) or text::ipXr (explicit)

ipXr

cidr

cidr(ipXr) or ipXr::cidr (explicit)

cidr

ipXr

ipXr(cidr) or cidr::ipXr (assignment)

ipXr

varbit

to_bit(ipXr) or ipXr::varbit (explicit)

varbit

ip4r

ip4r(varbit) or varbit::ip4r (explicit)

varbit

ip6r

ip6r(varbit) or varbit::ip6r (explicit)

Usage

Create the extension

CREATE EXTENSION ip4r;

Create a test table and import data

CREATE TABLE ipranges (r iprange, r4 ip4r, r6 ip6r);
INSERT INTO ipranges
    SELECT r, null, r
    FROM (
        SELECT ip6r(regexp_replace(ls, E'(....(?!$))', E'\\1:', 'g')::ip6,
               regexp_replace(substring(ls FOR n + 1) || substring(us FROM n + 2),
               E'(....(?!$))', E'\\1:', 'g')::ip6) AS r
        FROM (
            SELECT md5(i || ' lower 1') AS ls,
                   md5(i || ' upper 1') AS us,
                   (i % 11) + (i/11 % 11) + (i/121 % 11) AS n
            FROM generate_series(1,13310) i) s1) s2;

Create a GiST index

CREATE INDEX ipranges_r ON ipranges USING gist (r);

Use the contains operator

EXPLAIN (COSTS OFF) SELECT * FROM ipranges WHERE r >>= '5555::' ORDER BY r;

The following result is returned:

                     QUERY PLAN                      
-----------------------------------------------------
 Sort
   Sort Key: r
   ->  Bitmap Heap Scan on ipranges
         Recheck Cond: (r >>= '5555::'::iprange)
         ->  Bitmap Index Scan on ipranges_r
               Index Cond: (r >>= '5555::'::iprange)
(6 rows)

Uninstall the extension

DROP EXTENSION ip4r;