mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Add support for cross-type hashing in hash index searches and hash joins.
Hashing for aggregation purposes still needs work, so it's not time to mark any cross-type operators as hashable for general use, but these cases work if the operators are so marked by hand in the system catalogs.
This commit is contained in:
168
src/backend/utils/cache/lsyscache.c
vendored
168
src/backend/utils/cache/lsyscache.c
vendored
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.146 2007/01/22 01:35:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.147 2007/01/30 01:33:36 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Eventually, the index information should go through here, too.
|
||||
@ -389,23 +389,34 @@ get_mergejoin_opfamilies(Oid opno)
|
||||
}
|
||||
|
||||
/*
|
||||
* get_compatible_hash_operator
|
||||
* Get the OID of a hash equality operator compatible with the given
|
||||
* operator, but operating on its LHS or RHS datatype as specified.
|
||||
* get_compatible_hash_operators
|
||||
* Get the OID(s) of hash equality operator(s) compatible with the given
|
||||
* operator, but operating on its LHS and/or RHS datatype.
|
||||
*
|
||||
* If the given operator is not cross-type, the result should be the same
|
||||
* operator, but in cross-type situations it is different.
|
||||
* An operator for the LHS type is sought and returned into *lhs_opno if
|
||||
* lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
|
||||
* and returned into *rhs_opno if rhs_opno isn't NULL.
|
||||
*
|
||||
* Returns InvalidOid if no compatible operator can be found. (This indicates
|
||||
* that the operator should not have been marked oprcanhash.)
|
||||
* If the given operator is not cross-type, the results should be the same
|
||||
* operator, but in cross-type situations they will be different.
|
||||
*
|
||||
* Returns true if able to find the requested operator(s), false if not.
|
||||
* (This indicates that the operator should not have been marked oprcanhash.)
|
||||
*/
|
||||
Oid
|
||||
get_compatible_hash_operator(Oid opno, bool use_lhs_type)
|
||||
bool
|
||||
get_compatible_hash_operators(Oid opno,
|
||||
Oid *lhs_opno, Oid *rhs_opno)
|
||||
{
|
||||
Oid result = InvalidOid;
|
||||
bool result = false;
|
||||
CatCList *catlist;
|
||||
int i;
|
||||
|
||||
/* Ensure output args are initialized on failure */
|
||||
if (lhs_opno)
|
||||
*lhs_opno = InvalidOid;
|
||||
if (rhs_opno)
|
||||
*rhs_opno = InvalidOid;
|
||||
|
||||
/*
|
||||
* Search pg_amop to see if the target operator is registered as the "="
|
||||
* operator of any hash opfamily. If the operator is registered in
|
||||
@ -423,22 +434,53 @@ get_compatible_hash_operator(Oid opno, bool use_lhs_type)
|
||||
if (aform->amopmethod == HASH_AM_OID &&
|
||||
aform->amopstrategy == HTEqualStrategyNumber)
|
||||
{
|
||||
/* Found a suitable opfamily, get matching single-type operator */
|
||||
Oid typid;
|
||||
|
||||
/* No extra lookup needed if given operator is single-type */
|
||||
if (aform->amoplefttype == aform->amoprighttype)
|
||||
{
|
||||
result = opno;
|
||||
if (lhs_opno)
|
||||
*lhs_opno = opno;
|
||||
if (rhs_opno)
|
||||
*rhs_opno = opno;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
|
||||
result = get_opfamily_member(aform->amopfamily,
|
||||
typid, typid,
|
||||
HTEqualStrategyNumber);
|
||||
if (OidIsValid(result))
|
||||
/*
|
||||
* Get the matching single-type operator(s). Failure probably
|
||||
* shouldn't happen --- it implies a bogus opfamily --- but
|
||||
* continue looking if so.
|
||||
*/
|
||||
if (lhs_opno)
|
||||
{
|
||||
*lhs_opno = get_opfamily_member(aform->amopfamily,
|
||||
aform->amoplefttype,
|
||||
aform->amoplefttype,
|
||||
HTEqualStrategyNumber);
|
||||
if (!OidIsValid(*lhs_opno))
|
||||
continue;
|
||||
/* Matching LHS found, done if caller doesn't want RHS */
|
||||
if (!rhs_opno)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rhs_opno)
|
||||
{
|
||||
*rhs_opno = get_opfamily_member(aform->amopfamily,
|
||||
aform->amoprighttype,
|
||||
aform->amoprighttype,
|
||||
HTEqualStrategyNumber);
|
||||
if (!OidIsValid(*rhs_opno))
|
||||
{
|
||||
/* Forget any LHS operator from this opfamily */
|
||||
if (lhs_opno)
|
||||
*lhs_opno = InvalidOid;
|
||||
continue;
|
||||
}
|
||||
/* Matching RHS found, so done */
|
||||
result = true;
|
||||
break;
|
||||
/* failure probably shouldn't happen, but keep looking if so */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,28 +490,38 @@ get_compatible_hash_operator(Oid opno, bool use_lhs_type)
|
||||
}
|
||||
|
||||
/*
|
||||
* get_op_hash_function
|
||||
* Get the OID of the datatype-specific hash function associated with
|
||||
* a hashable equality operator.
|
||||
* get_op_hash_functions
|
||||
* Get the OID(s) of hash support function(s) compatible with the given
|
||||
* operator, operating on its LHS and/or RHS datatype as required.
|
||||
*
|
||||
* XXX API needs to be generalized for the case of different left and right
|
||||
* datatypes.
|
||||
* A function for the LHS type is sought and returned into *lhs_procno if
|
||||
* lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
|
||||
* and returned into *rhs_procno if rhs_procno isn't NULL.
|
||||
*
|
||||
* Returns InvalidOid if no hash function can be found. (This indicates
|
||||
* that the operator should not have been marked oprcanhash.)
|
||||
* If the given operator is not cross-type, the results should be the same
|
||||
* function, but in cross-type situations they will be different.
|
||||
*
|
||||
* Returns true if able to find the requested function(s), false if not.
|
||||
* (This indicates that the operator should not have been marked oprcanhash.)
|
||||
*/
|
||||
Oid
|
||||
get_op_hash_function(Oid opno)
|
||||
bool
|
||||
get_op_hash_functions(Oid opno,
|
||||
RegProcedure *lhs_procno, RegProcedure *rhs_procno)
|
||||
{
|
||||
Oid result = InvalidOid;
|
||||
bool result = false;
|
||||
CatCList *catlist;
|
||||
int i;
|
||||
|
||||
/* Ensure output args are initialized on failure */
|
||||
if (lhs_procno)
|
||||
*lhs_procno = InvalidOid;
|
||||
if (rhs_procno)
|
||||
*rhs_procno = InvalidOid;
|
||||
|
||||
/*
|
||||
* Search pg_amop to see if the target operator is registered as the "="
|
||||
* operator of any hash opfamily. If the operator is registered in
|
||||
* multiple opfamilies, assume we can use the associated hash function from
|
||||
* any one.
|
||||
* multiple opfamilies, assume we can use any one.
|
||||
*/
|
||||
catlist = SearchSysCacheList(AMOPOPID, 1,
|
||||
ObjectIdGetDatum(opno),
|
||||
@ -483,12 +535,50 @@ get_op_hash_function(Oid opno)
|
||||
if (aform->amopmethod == HASH_AM_OID &&
|
||||
aform->amopstrategy == HTEqualStrategyNumber)
|
||||
{
|
||||
/* Found a suitable opfamily, get matching hash support function */
|
||||
result = get_opfamily_proc(aform->amopfamily,
|
||||
aform->amoplefttype,
|
||||
aform->amoprighttype,
|
||||
HASHPROC);
|
||||
break;
|
||||
/*
|
||||
* Get the matching support function(s). Failure probably
|
||||
* shouldn't happen --- it implies a bogus opfamily --- but
|
||||
* continue looking if so.
|
||||
*/
|
||||
if (lhs_procno)
|
||||
{
|
||||
*lhs_procno = get_opfamily_proc(aform->amopfamily,
|
||||
aform->amoplefttype,
|
||||
aform->amoplefttype,
|
||||
HASHPROC);
|
||||
if (!OidIsValid(*lhs_procno))
|
||||
continue;
|
||||
/* Matching LHS found, done if caller doesn't want RHS */
|
||||
if (!rhs_procno)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
/* Only one lookup needed if given operator is single-type */
|
||||
if (aform->amoplefttype == aform->amoprighttype)
|
||||
{
|
||||
*rhs_procno = *lhs_procno;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rhs_procno)
|
||||
{
|
||||
*rhs_procno = get_opfamily_proc(aform->amopfamily,
|
||||
aform->amoprighttype,
|
||||
aform->amoprighttype,
|
||||
HASHPROC);
|
||||
if (!OidIsValid(*rhs_procno))
|
||||
{
|
||||
/* Forget any LHS function from this opfamily */
|
||||
if (lhs_procno)
|
||||
*lhs_procno = InvalidOid;
|
||||
continue;
|
||||
}
|
||||
/* Matching RHS found, so done */
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user