Skip to content

Commit e1fbe11

Browse files
committed
Fix BRIN minmax-multi distance for inet type
The distance calculation ignored the mask, unlike the inet comparator, which resulted in negative distance in some cases. Fixed by applying the mask in brin_minmax_multi_distance_inet. I've considered simply calling inetmi() to calculate the delta, but that does not consider mask either. Reviewed-by: Zhihong Yu Discussion: https://postgr.es/m/1a0a7b9d-9bda-e3a2-7fa4-88f15042a051%40enterprisedb.com
1 parent 7262f24 commit e1fbe11

File tree

1 file changed

+51
-8
lines changed

1 file changed

+51
-8
lines changed

src/backend/access/brin/brin_minmax_multi.c

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,31 +2297,74 @@ brin_minmax_multi_distance_inet(PG_FUNCTION_ARGS)
22972297
inet *ipa = PG_GETARG_INET_PP(0);
22982298
inet *ipb = PG_GETARG_INET_PP(1);
22992299

2300+
int lena,
2301+
lenb;
2302+
23002303
/*
23012304
* If the addresses are from different families, consider them to be in
23022305
* maximal possible distance (which is 1.0).
23032306
*/
23042307
if (ip_family(ipa) != ip_family(ipb))
23052308
PG_RETURN_FLOAT8(1.0);
23062309

2307-
/* ipv4 or ipv6 */
2308-
if (ip_family(ipa) == PGSQL_AF_INET)
2309-
len = 4;
2310-
else
2311-
len = 16; /* NS_IN6ADDRSZ */
2310+
addra = (unsigned char *) palloc(ip_addrsize(ipa));
2311+
memcpy(addra, ip_addr(ipa), ip_addrsize(ipa));
2312+
2313+
addrb = (unsigned char *) palloc(ip_addrsize(ipb));
2314+
memcpy(addrb, ip_addr(ipb), ip_addrsize(ipb));
2315+
2316+
/*
2317+
* The length is calculated from the mask length, because we sort the
2318+
* addresses by first address in the range, so A.B.C.D/24 < A.B.C.1
2319+
* (the first range starts at A.B.C.0, which is before A.B.C.1). We
2320+
* don't want to produce negative delta in this case, so we just cut
2321+
* the extra bytes.
2322+
*
2323+
* XXX Maybe this should be a bit more careful and cut the bits, not
2324+
* just whole bytes.
2325+
*/
2326+
lena = ip_bits(ipa);
2327+
lenb = ip_bits(ipb);
2328+
2329+
len = ip_addrsize(ipa);
2330+
2331+
/* apply the network mask to both addresses */
2332+
for (i = 0; i < len; i++)
2333+
{
2334+
unsigned char mask;
2335+
int nbits;
23122336

2313-
addra = ip_addr(ipa);
2314-
addrb = ip_addr(ipb);
2337+
nbits = lena - (i * 8);
2338+
if (nbits < 8)
2339+
{
2340+
mask = (0xFF << (8 - nbits));
2341+
addra[i] = (addra[i] & mask);
2342+
}
23152343

2344+
nbits = lenb - (i * 8);
2345+
if (nbits < 8)
2346+
{
2347+
mask = (0xFF << (8 - nbits));
2348+
addrb[i] = (addrb[i] & mask);
2349+
}
2350+
}
2351+
2352+
/* Calculate the difference between the addresses. */
23162353
delta = 0;
23172354
for (i = len - 1; i >= 0; i--)
23182355
{
2319-
delta += (float8) addrb[i] - (float8) addra[i];
2356+
unsigned char a = addra[i];
2357+
unsigned char b = addrb[i];
2358+
2359+
delta += (float8) b - (float8) a;
23202360
delta /= 256;
23212361
}
23222362

23232363
Assert((delta >= 0) && (delta <= 1));
23242364

2365+
pfree(addra);
2366+
pfree(addrb);
2367+
23252368
PG_RETURN_FLOAT8(delta);
23262369
}
23272370

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy