1997-11-25 17:07:18 -05:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
*
|
Clean up two rather nasty bugs in operator selection code.
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
2001-02-15 22:16:58 -05:00
|
|
|
* parse_oper.h
|
2002-11-29 16:39:12 -05:00
|
|
|
* handle operator things for parser
|
1997-11-25 17:07:18 -05:00
|
|
|
*
|
|
|
|
|
*
|
2025-01-01 11:21:55 -05:00
|
|
|
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
|
2000-01-26 00:58:53 -05:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1997-11-25 17:07:18 -05:00
|
|
|
*
|
2010-09-20 16:08:53 -04:00
|
|
|
* src/include/parser/parse_oper.h
|
1997-11-25 17:07:18 -05:00
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
#ifndef PARSE_OPER_H
|
|
|
|
|
#define PARSE_OPER_H
|
|
|
|
|
|
1999-07-15 11:21:54 -04:00
|
|
|
#include "access/htup.h"
|
2016-12-28 12:00:00 -05:00
|
|
|
#include "nodes/parsenodes.h"
|
2003-04-29 18:13:11 -04:00
|
|
|
#include "parser/parse_node.h"
|
|
|
|
|
|
1997-11-25 17:07:18 -05:00
|
|
|
|
|
|
|
|
typedef HeapTuple Operator;
|
|
|
|
|
|
2002-04-16 19:08:12 -04:00
|
|
|
/* Routines to look up an operator given name and exact input type(s) */
|
2006-03-14 17:48:25 -05:00
|
|
|
extern Oid LookupOperName(ParseState *pstate, List *opername,
|
|
|
|
|
Oid oprleft, Oid oprright,
|
|
|
|
|
bool noError, int location);
|
2016-12-28 12:00:00 -05:00
|
|
|
extern Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError);
|
2002-04-16 19:08:12 -04:00
|
|
|
|
Clean up two rather nasty bugs in operator selection code.
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
2001-02-15 22:16:58 -05:00
|
|
|
/* Routines to find operators matching a name and given input types */
|
|
|
|
|
/* NB: the selected operator may require coercion of the input types! */
|
2022-09-20 16:09:30 -04:00
|
|
|
extern Operator oper(ParseState *pstate, List *opname, Oid ltypeId,
|
|
|
|
|
Oid rtypeId, bool noError, int location);
|
2006-03-14 17:48:25 -05:00
|
|
|
extern Operator left_oper(ParseState *pstate, List *op, Oid arg,
|
|
|
|
|
bool noError, int location);
|
1997-11-25 17:07:18 -05:00
|
|
|
|
Clean up two rather nasty bugs in operator selection code.
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
2001-02-15 22:16:58 -05:00
|
|
|
/* Routines to find operators that DO NOT require coercion --- ie, their */
|
|
|
|
|
/* input types are either exactly as given, or binary-compatible */
|
2006-03-14 17:48:25 -05:00
|
|
|
extern Operator compatible_oper(ParseState *pstate, List *op,
|
|
|
|
|
Oid arg1, Oid arg2,
|
|
|
|
|
bool noError, int location);
|
2001-03-21 23:01:46 -05:00
|
|
|
|
Clean up two rather nasty bugs in operator selection code.
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
2001-02-15 22:16:58 -05:00
|
|
|
/* currently no need for compatible_left_oper/compatible_right_oper */
|
|
|
|
|
|
Extend ALTER OPERATOR to allow setting more optimization attributes.
Allow the COMMUTATOR, NEGATOR, MERGES, and HASHES attributes to be set
by ALTER OPERATOR. However, we don't allow COMMUTATOR/NEGATOR to be
changed once set, nor allow the MERGES/HASHES flags to be unset once
set. Changes like that might invalidate plans already made, and
dealing with the consequences seems like more trouble than it's worth.
The main use-case we foresee for this is to allow addition of missed
properties in extension update scripts, such as extending an existing
operator to support hashing. So only transitions from not-set to set
states seem very useful.
This patch also causes us to reject some incorrect cases that formerly
resulted in inconsistent catalog state, such as trying to set the
commutator of an operator to be some other operator that already has a
(different) commutator.
While at it, move the InvokeObjectPostCreateHook call for CREATE
OPERATOR to not occur until after we've fixed up commutator or negator
links as needed. The previous ordering could only be justified by
thinking of the OperatorUpd call as a kind of ALTER OPERATOR step;
but we don't call InvokeObjectPostAlterHook therein. It seems better
to let the hook see the final state of the operator object.
In the documentation, move the discussion of how to establish
commutator pairs from xoper.sgml to the CREATE OPERATOR ref page.
Tommy Pavlicek, reviewed and editorialized a bit by me
Discussion: https://postgr.es/m/CAEhP-W-vGVzf4udhR5M8Bdv88UYnPrhoSkj3ieR3QNrsGQoqdg@mail.gmail.com
2023-10-20 12:28:38 -04:00
|
|
|
/* Error reporting support */
|
|
|
|
|
extern const char *op_signature_string(List *op, Oid arg1, Oid arg2);
|
|
|
|
|
|
2008-08-02 17:32:01 -04:00
|
|
|
/* Routines for identifying "<", "=", ">" operators for a type */
|
|
|
|
|
extern void get_sort_group_operators(Oid argtype,
|
|
|
|
|
bool needLT, bool needEQ, bool needGT,
|
2010-10-30 21:55:20 -04:00
|
|
|
Oid *ltOpr, Oid *eqOpr, Oid *gtOpr,
|
|
|
|
|
bool *isHashable);
|
2000-11-16 17:30:52 -05:00
|
|
|
|
2002-11-29 16:39:12 -05:00
|
|
|
/* Convenience routines for common calls on the above */
|
|
|
|
|
extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
|
Clean up two rather nasty bugs in operator selection code.
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
2001-02-15 22:16:58 -05:00
|
|
|
|
|
|
|
|
/* Extract operator OID or underlying-function OID from an Operator tuple */
|
|
|
|
|
extern Oid oprid(Operator op);
|
|
|
|
|
extern Oid oprfuncid(Operator op);
|
2001-10-28 01:26:15 -05:00
|
|
|
|
2003-04-08 19:20:04 -04:00
|
|
|
/* Build expression tree for an operator invocation */
|
2003-04-29 18:13:11 -04:00
|
|
|
extern Expr *make_op(ParseState *pstate, List *opname,
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-13 23:46:39 -04:00
|
|
|
Node *ltree, Node *rtree, Node *last_srf, int location);
|
2003-06-28 20:33:44 -04:00
|
|
|
extern Expr *make_scalar_array_op(ParseState *pstate, List *opname,
|
|
|
|
|
bool useOr,
|
2006-03-14 17:48:25 -05:00
|
|
|
Node *ltree, Node *rtree, int location);
|
2003-04-08 19:20:04 -04:00
|
|
|
|
1997-11-25 17:07:18 -05:00
|
|
|
#endif /* PARSE_OPER_H */
|