mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Fix failure to check whether a rowtype's component types are sortable.
The existence of a btree opclass accepting composite types caused us to assume that every composite type is sortable. This isn't true of course; we need to check if the column types are all sortable. There was logic for this for the case of array comparison (ie, check that the element type is sortable), but we missed the point for rowtypes. Per Teodor's report of an ANALYZE failure for an unsortable composite type. Rather than just add some more ad-hoc logic for this, I moved knowledge of the issue into typcache.c. The typcache will now only report out array_eq, record_cmp, and friends as usable operators if the array or composite type will work with those functions. Unfortunately we don't have enough info to do this for anonymous RECORD types; in that case, just assume it will work, and take the runtime failure as before if it doesn't. This patch might be a candidate for back-patching at some point, but given the lack of complaints from the field, I'd rather just test it in HEAD for now. Note: most of the places touched in this patch will need further work when we get around to supporting hashing of record types.
This commit is contained in:
61
src/backend/utils/cache/lsyscache.c
vendored
61
src/backend/utils/cache/lsyscache.c
vendored
@ -33,6 +33,7 @@
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datum.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/typcache.h"
|
||||
@ -1120,34 +1121,35 @@ op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
|
||||
* opfamily entries for this operator and associated sortops. The pg_operator
|
||||
* flag is just a hint to tell the planner whether to bother looking.)
|
||||
*
|
||||
* In some cases (currently only array_eq), mergejoinability depends on the
|
||||
* specific input data type the operator is invoked for, so that must be
|
||||
* passed as well. We currently assume that only one input's type is needed
|
||||
* to check this --- by convention, pass the left input's data type.
|
||||
* In some cases (currently only array_eq and record_eq), mergejoinability
|
||||
* depends on the specific input data type the operator is invoked for, so
|
||||
* that must be passed as well. We currently assume that only one input's type
|
||||
* is needed to check this --- by convention, pass the left input's data type.
|
||||
*/
|
||||
bool
|
||||
op_mergejoinable(Oid opno, Oid inputtype)
|
||||
{
|
||||
HeapTuple tp;
|
||||
bool result = false;
|
||||
HeapTuple tp;
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
/*
|
||||
* For array_eq or record_eq, we can sort if the element or field types
|
||||
* are all sortable. We could implement all the checks for that here, but
|
||||
* the typcache already does that and caches the results too, so let's
|
||||
* rely on the typcache.
|
||||
*/
|
||||
if (opno == ARRAY_EQ_OP)
|
||||
{
|
||||
/*
|
||||
* For array_eq, can sort if element type has a default btree opclass.
|
||||
* We could use GetDefaultOpClass, but that's fairly expensive and not
|
||||
* cached, so let's use the typcache instead.
|
||||
*/
|
||||
Oid elem_type = get_base_element_type(inputtype);
|
||||
|
||||
if (OidIsValid(elem_type))
|
||||
{
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
typentry = lookup_type_cache(elem_type, TYPECACHE_BTREE_OPFAMILY);
|
||||
if (OidIsValid(typentry->btree_opf))
|
||||
result = true;
|
||||
}
|
||||
typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
|
||||
if (typentry->cmp_proc == F_BTARRAYCMP)
|
||||
result = true;
|
||||
}
|
||||
else if (opno == RECORD_EQ_OP)
|
||||
{
|
||||
typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
|
||||
if (typentry->cmp_proc == F_BTRECORDCMP)
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1178,22 +1180,17 @@ op_mergejoinable(Oid opno, Oid inputtype)
|
||||
bool
|
||||
op_hashjoinable(Oid opno, Oid inputtype)
|
||||
{
|
||||
HeapTuple tp;
|
||||
bool result = false;
|
||||
HeapTuple tp;
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
/* As in op_mergejoinable, let the typcache handle the hard cases */
|
||||
/* Eventually we'll need a similar case for record_eq ... */
|
||||
if (opno == ARRAY_EQ_OP)
|
||||
{
|
||||
/* For array_eq, can hash if element type has a default hash opclass */
|
||||
Oid elem_type = get_base_element_type(inputtype);
|
||||
|
||||
if (OidIsValid(elem_type))
|
||||
{
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
typentry = lookup_type_cache(elem_type, TYPECACHE_HASH_OPFAMILY);
|
||||
if (OidIsValid(typentry->hash_opf))
|
||||
result = true;
|
||||
}
|
||||
typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
|
||||
if (typentry->hash_proc == F_HASH_ARRAY)
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user