diff options
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 168 |
1 files changed, 129 insertions, 39 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index c449ad6e742..8946cb73151 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -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; + } } } |