mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
1. If there is exactly one pg_operator entry of the right name and oprkind, oper() and related routines would return that entry whether its input type had anything to do with the request or not. This is just premature optimization: we shouldn't return the single candidate until after we verify that it really is a valid candidate, ie, is at least coercion-compatible with the given types. 2. oper() and related routines only promise a coercion-compatible result. Unfortunately, there were quite a few callers that assumed the returned operator is binary-compatible with the given datatype; they would proceed to call it without making any datatype coercions. These callers include sorting, grouping, aggregation, and VACUUM ANALYZE. In general I think it is appropriate for these callers to require an exact or binary-compatible match, so I've added a new routine compatible_oper() that only succeeds if it can find an operator that doesn't require any run-time conversions. Callers now call oper() or compatible_oper() depending on whether they are prepared to deal with type conversion or not. The upshot of these bugs is revealed by the following silliness in PL/Tcl's selftest: it creates an operator @< on int4, and then tries to use it to sort a char(N) column. The system would let it do that :-( (and evidently has done so since 6.3 :-( :-(). The result in this case was just a silly sort order, but the reverse combination would've provoked coredump from trying to dereference integers. With this fix you get more reasonable behavior: pltcl_test=# select * from T_pkey1 order by key1, key2 using @<; ERROR: Unable to identify an operator '@<' for types 'bpchar' and 'bpchar' You will have to retype this query using an explicit cast
45 lines
1.6 KiB
C
45 lines
1.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* parse_oper.h
|
|
*
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* $Id: parse_oper.h,v 1.14 2001/02/16 03:16:58 tgl Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PARSE_OPER_H
|
|
#define PARSE_OPER_H
|
|
|
|
#include "access/htup.h"
|
|
|
|
typedef HeapTuple Operator;
|
|
|
|
/* Routines to find operators matching a name and given input types */
|
|
/* NB: the selected operator may require coercion of the input types! */
|
|
extern Operator oper(char *op, Oid arg1, Oid arg2, bool noError);
|
|
extern Operator right_oper(char *op, Oid arg);
|
|
extern Operator left_oper(char *op, Oid arg);
|
|
|
|
/* Routines to find operators that DO NOT require coercion --- ie, their */
|
|
/* input types are either exactly as given, or binary-compatible */
|
|
extern Operator compatible_oper(char *op, Oid arg1, Oid arg2, bool noError);
|
|
/* currently no need for compatible_left_oper/compatible_right_oper */
|
|
|
|
/* Convenience routines that call compatible_oper() and return either */
|
|
/* the operator OID or the underlying function OID, or InvalidOid if fail */
|
|
extern Oid compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError);
|
|
extern Oid compatible_oper_funcid(char *op, Oid arg1, Oid arg2, bool noError);
|
|
|
|
/* Convenience routine that packages a specific call on compatible_oper */
|
|
extern Oid any_ordering_op(Oid argtype);
|
|
|
|
/* Extract operator OID or underlying-function OID from an Operator tuple */
|
|
extern Oid oprid(Operator op);
|
|
extern Oid oprfuncid(Operator op);
|
|
|
|
#endif /* PARSE_OPER_H */
|