mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Give inet/cidr datatypes their own hash function that ignores the inet vs
cidr type bit, the same as network_eq does. This is needed for hash joins and hash aggregation to work correctly on these types. Per bug report from Michael Fuhr, 2004-04-13. Also, improve hash function for int8 as suggested by Greg Stark.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.39 2003/11/29 19:51:40 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.40 2004/06/13 21:57:24 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* These functions are stored in pg_amproc. For each operator class
|
||||
@@ -44,8 +44,26 @@ hashint4(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
hashint8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* we just use the low 32 bits... */
|
||||
/*
|
||||
* The idea here is to produce a hash value compatible with the values
|
||||
* produced by hashint4 and hashint2 for logically equivalent inputs;
|
||||
* this is necessary if we ever hope to support cross-type hash joins
|
||||
* across these input types. Since all three types are signed, we can
|
||||
* xor the high half of the int8 value if the sign is positive, or the
|
||||
* complement of the high half when the sign is negative.
|
||||
*/
|
||||
#ifndef INT64_IS_BUSTED
|
||||
int64 val = PG_GETARG_INT64(0);
|
||||
uint32 lohalf = (uint32) val;
|
||||
uint32 hihalf = (uint32) (val >> 32);
|
||||
|
||||
lohalf ^= (val >= 0) ? hihalf : ~hihalf;
|
||||
|
||||
PG_RETURN_UINT32(~lohalf);
|
||||
#else
|
||||
/* here if we can't count on "x >> 32" to work sanely */
|
||||
PG_RETURN_UINT32(~((uint32) PG_GETARG_INT64(0)));
|
||||
#endif
|
||||
}
|
||||
|
||||
Datum
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for the INET and CIDR types.
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.51 2004/06/13 19:56:50 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.52 2004/06/13 21:57:25 tgl Exp $
|
||||
*
|
||||
* Jon Postel RIP 16 Oct 1998
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "access/hash.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "libpq/ip.h"
|
||||
#include "libpq/libpq-be.h"
|
||||
@@ -42,7 +42,7 @@ static int ip_addrsize(inet *inetptr);
|
||||
(((inet_struct *)VARDATA(inetptr))->type)
|
||||
|
||||
#define ip_addr(inetptr) \
|
||||
(((inet_struct *)VARDATA(inetptr))->ip_addr)
|
||||
(((inet_struct *)VARDATA(inetptr))->ipaddr)
|
||||
|
||||
#define ip_maxbits(inetptr) \
|
||||
(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
|
||||
@@ -60,7 +60,7 @@ ip_addrsize(inet *inetptr)
|
||||
case PGSQL_AF_INET6:
|
||||
return 16;
|
||||
default:
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +424,27 @@ network_ne(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support function for hash indexes on inet/cidr.
|
||||
*
|
||||
* Since network_cmp considers only ip_family, ip_bits, and ip_addr,
|
||||
* only these fields may be used in the hash; in particular don't use type.
|
||||
*/
|
||||
Datum
|
||||
hashinet(PG_FUNCTION_ARGS)
|
||||
{
|
||||
inet *addr = PG_GETARG_INET_P(0);
|
||||
int addrsize = ip_addrsize(addr);
|
||||
unsigned char key[sizeof(inet_struct)];
|
||||
|
||||
Assert(addrsize + 2 <= sizeof(key));
|
||||
key[0] = ip_family(addr);
|
||||
key[1] = ip_bits(addr);
|
||||
memcpy(key + 2, ip_addr(addr), addrsize);
|
||||
|
||||
return hash_any(key, addrsize + 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Boolean network-inclusion tests.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user