mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Provide hashing support for arrays.
The core of this patch is hash_array() and associated typcache infrastructure, which works just about exactly like the existing support for array comparison. In addition I did some work to ensure that the planner won't think that an array type is hashable unless its element type is hashable, and similarly for sorting. This includes adding a datatype parameter to op_hashjoinable and op_mergejoinable, and adding an explicit "hashable" flag to SortGroupClause. The lack of a cross-check on the element type was a pre-existing bug in mergejoin support --- but it didn't matter so much before, because if you couldn't sort the element type there wasn't any good alternative to failing anyhow. Now that we have the alternative of hashing the array type, there are cases where we can avoid a failure by being picky at the planner stage, so it's time to be picky. The issue of exactly how to combine the per-element hash values to produce an array hash is still open for discussion, but the rest of this is pretty solid, so I'll commit it as-is.
This commit is contained in:
@ -861,28 +861,45 @@ testexpr_is_hashable(Node *testexpr)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check expression is hashable + strict
|
||||
*
|
||||
* We could use op_hashjoinable() and op_strict(), but do it like this to
|
||||
* avoid a redundant cache lookup.
|
||||
*/
|
||||
static bool
|
||||
hash_ok_operator(OpExpr *expr)
|
||||
{
|
||||
Oid opid = expr->opno;
|
||||
HeapTuple tup;
|
||||
Form_pg_operator optup;
|
||||
|
||||
/* quick out if not a binary operator */
|
||||
if (list_length(expr->args) != 2)
|
||||
return false;
|
||||
/* else must look up the operator properties */
|
||||
tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for operator %u", opid);
|
||||
optup = (Form_pg_operator) GETSTRUCT(tup);
|
||||
if (!optup->oprcanhash || !func_strict(optup->oprcode))
|
||||
if (opid == ARRAY_EQ_OP)
|
||||
{
|
||||
ReleaseSysCache(tup);
|
||||
return false;
|
||||
/* array_eq is strict, but must check input type to ensure hashable */
|
||||
Node *leftarg = linitial(expr->args);
|
||||
|
||||
return op_hashjoinable(opid, exprType(leftarg));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else must look up the operator properties */
|
||||
HeapTuple tup;
|
||||
Form_pg_operator optup;
|
||||
|
||||
tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for operator %u", opid);
|
||||
optup = (Form_pg_operator) GETSTRUCT(tup);
|
||||
if (!optup->oprcanhash || !func_strict(optup->oprcode))
|
||||
{
|
||||
ReleaseSysCache(tup);
|
||||
return false;
|
||||
}
|
||||
ReleaseSysCache(tup);
|
||||
return true;
|
||||
}
|
||||
ReleaseSysCache(tup);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user