As IPV6 needs 128 bits(16 bytes) then why in postgres CIDR datatype has storage as 24 byte(8.1) and 19byte(9.1)?

StackOverflow https://stackoverflow.com/questions/11542680

Question

i am working with ipv4 and ipv6 to store in postgres db.

as ipv4 needs 32 bits(4byte) and ipv6 needs 128(16byte) bits.then why in postgres CIDR and INET datatype has the storage as 12 byte and 24 bytes respectively for IPV4 and IPV6(8.1).

with 9.1,it has 7 byte and 19 byte respectively for IPV4 and IPV6.

i don't understand why it needs extra byte more than 16 byte for storing IPV6 and 4 byte for IPV4??

http://www.postgresql.org/docs/8.1/static/datatype-net-types.html

http://www.postgresql.org/docs/9.1/interactive/datatype-net-types.html

Was it helpful?

Solution

The sourcecode for the IP datatypes show this:

typedef struct
{
    unsigned char family;       /* PGSQL_AF_INET or PGSQL_AF_INET6 */
    unsigned char bits;         /* number of bits in netmask */
    unsigned char ipaddr[16];   /* up to 128 bits of address */
} inet_struct;

This means, that additionally to the "raw" data in ipaddr (4 bytes for IP4, 16 bytes for IP6) there is one byte for the netmask and and one byte for the address family (basically a switch for IP4/IP6).

Additionally there is the varlena overhead which is mentioned in the same file:

/*
 * Both INET and CIDR addresses are represented within Postgres as varlena
 * objects, ie, there is a varlena header in front of the struct type
 * depicted above.  This struct depicts what we actually have in memory
 * in "uncompressed" cases.  Note that since the maximum data size is only
 * 18 bytes, INET/CIDR will invariably be stored into tuples using the
 * 1-byte-header varlena format.  However, we have to be prepared to cope
 * with the 4-byte-header format too, because various code may helpfully
 * try to "decompress" 1-byte-header datums.
 */
typedef struct
{
    char        vl_len_[4];     /* Do not touch this field directly! */
    inet_struct inet_data;
} inet;

So the equation for IP4 is this:

1 byte varlena
1 byte address family
1 byte netmask
4 raw bytes
=========== 
7 byte total

For IP6 the same formula gives you 19 bytes.

EDIT Older versions of PostgreSQL did only have 4 byte varlena representation. Therefore you can add 3 bytes for each type (IP4: 10, IP6: 22). On top of that there was a padding up to the next 4 byte border. This gives you 2 bytes for each type adding up to 12 or 24 bytes.

This mail sheds some light upon the development of the shorter version.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top