2015-12-31 23:37:31 +01:00
|
|
|
CREATE FUNCTION alter_op_test_fn(boolean, boolean)
|
2015-07-14 17:17:55 +02:00
|
|
|
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
|
2015-12-31 23:37:31 +01:00
|
|
|
CREATE FUNCTION customcontsel(internal, oid, internal, integer)
|
|
|
|
RETURNS float8 AS 'contsel' LANGUAGE internal STABLE STRICT;
|
2015-07-14 17:17:55 +02:00
|
|
|
CREATE OPERATOR === (
|
|
|
|
LEFTARG = boolean,
|
|
|
|
RIGHTARG = boolean,
|
|
|
|
PROCEDURE = alter_op_test_fn,
|
|
|
|
COMMUTATOR = ===,
|
|
|
|
NEGATOR = !==,
|
2015-12-31 23:37:31 +01:00
|
|
|
RESTRICT = customcontsel,
|
2015-07-14 17:17:55 +02:00
|
|
|
JOIN = contjoinsel,
|
|
|
|
HASHES, MERGES
|
|
|
|
);
|
2015-12-31 23:37:31 +01:00
|
|
|
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_operator'::regclass AND
|
|
|
|
objid = '===(bool,bool)'::regoperator
|
|
|
|
ORDER BY 1;
|
|
|
|
ref | deptype
|
|
|
|
-------------------------------------------------------+---------
|
|
|
|
function alter_op_test_fn(boolean,boolean) | n
|
|
|
|
function customcontsel(internal,oid,internal,integer) | n
|
|
|
|
schema public | n
|
|
|
|
(3 rows)
|
|
|
|
|
2015-07-14 17:17:55 +02:00
|
|
|
--
|
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 18:28:38 +02:00
|
|
|
-- Test resetting and setting restrict and join attributes.
|
2015-07-14 17:17:55 +02:00
|
|
|
--
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (JOIN = NONE);
|
|
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
|
|
|
oprrest | oprjoin
|
|
|
|
---------+---------
|
|
|
|
- | -
|
|
|
|
(1 row)
|
|
|
|
|
2015-12-31 23:37:31 +01:00
|
|
|
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_operator'::regclass AND
|
|
|
|
objid = '===(bool,bool)'::regoperator
|
|
|
|
ORDER BY 1;
|
|
|
|
ref | deptype
|
|
|
|
--------------------------------------------+---------
|
|
|
|
function alter_op_test_fn(boolean,boolean) | n
|
|
|
|
schema public | n
|
|
|
|
(2 rows)
|
|
|
|
|
2015-07-14 17:17:55 +02:00
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel);
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (JOIN = contjoinsel);
|
|
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
|
|
|
oprrest | oprjoin
|
|
|
|
---------+-------------
|
|
|
|
contsel | contjoinsel
|
|
|
|
(1 row)
|
|
|
|
|
2015-12-31 23:37:31 +01:00
|
|
|
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_operator'::regclass AND
|
|
|
|
objid = '===(bool,bool)'::regoperator
|
|
|
|
ORDER BY 1;
|
|
|
|
ref | deptype
|
|
|
|
--------------------------------------------+---------
|
|
|
|
function alter_op_test_fn(boolean,boolean) | n
|
|
|
|
schema public | n
|
|
|
|
(2 rows)
|
|
|
|
|
2015-07-14 17:17:55 +02:00
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE, JOIN = NONE);
|
|
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
|
|
|
oprrest | oprjoin
|
|
|
|
---------+---------
|
|
|
|
- | -
|
|
|
|
(1 row)
|
|
|
|
|
2015-12-31 23:37:31 +01:00
|
|
|
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_operator'::regclass AND
|
|
|
|
objid = '===(bool,bool)'::regoperator
|
|
|
|
ORDER BY 1;
|
|
|
|
ref | deptype
|
|
|
|
--------------------------------------------+---------
|
|
|
|
function alter_op_test_fn(boolean,boolean) | n
|
|
|
|
schema public | n
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = customcontsel, JOIN = contjoinsel);
|
2015-07-14 17:17:55 +02:00
|
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
2015-12-31 23:37:31 +01:00
|
|
|
oprrest | oprjoin
|
|
|
|
---------------+-------------
|
|
|
|
customcontsel | contjoinsel
|
2015-07-14 17:17:55 +02:00
|
|
|
(1 row)
|
|
|
|
|
2015-12-31 23:37:31 +01:00
|
|
|
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_operator'::regclass AND
|
|
|
|
objid = '===(bool,bool)'::regoperator
|
|
|
|
ORDER BY 1;
|
|
|
|
ref | deptype
|
|
|
|
-------------------------------------------------------+---------
|
|
|
|
function alter_op_test_fn(boolean,boolean) | n
|
|
|
|
function customcontsel(internal,oid,internal,integer) | n
|
|
|
|
schema public | n
|
|
|
|
(3 rows)
|
|
|
|
|
2015-07-14 17:17:55 +02:00
|
|
|
--
|
|
|
|
-- Test invalid options.
|
|
|
|
--
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = non_existent_func);
|
|
|
|
ERROR: function non_existent_func(internal, oid, internal, integer) does not exist
|
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (JOIN = non_existent_func);
|
|
|
|
ERROR: function non_existent_func(internal, oid, internal, smallint, internal) does not exist
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
-- invalid: non-lowercase quoted identifiers
|
|
|
|
ALTER OPERATOR & (bit, bit) SET ("Restrict" = _int_contsel, "Join" = _int_contjoinsel);
|
|
|
|
ERROR: operator attribute "Restrict" not recognized
|
2015-07-14 17:17:55 +02:00
|
|
|
--
|
|
|
|
-- Test permission check. Must be owner to ALTER OPERATOR.
|
|
|
|
--
|
2016-07-18 00:42:31 +02:00
|
|
|
CREATE USER regress_alter_op_user;
|
|
|
|
SET SESSION AUTHORIZATION regress_alter_op_user;
|
2015-07-14 17:17:55 +02:00
|
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
|
2015-07-17 20:10:52 +02:00
|
|
|
ERROR: must be owner of operator ===
|
|
|
|
RESET SESSION AUTHORIZATION;
|
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 18:28:38 +02:00
|
|
|
--
|
|
|
|
-- Test setting commutator, negator, merges, and hashes attributes,
|
|
|
|
-- which can only be set if not already set
|
|
|
|
--
|
|
|
|
CREATE FUNCTION alter_op_test_fn_bool_real(boolean, real)
|
|
|
|
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
|
|
|
|
CREATE FUNCTION alter_op_test_fn_real_bool(real, boolean)
|
|
|
|
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
|
|
|
|
-- operator
|
|
|
|
CREATE OPERATOR === (
|
|
|
|
LEFTARG = boolean,
|
|
|
|
RIGHTARG = real,
|
|
|
|
PROCEDURE = alter_op_test_fn_bool_real
|
|
|
|
);
|
|
|
|
-- commutator
|
|
|
|
CREATE OPERATOR ==== (
|
|
|
|
LEFTARG = real,
|
|
|
|
RIGHTARG = boolean,
|
|
|
|
PROCEDURE = alter_op_test_fn_real_bool
|
|
|
|
);
|
|
|
|
-- negator
|
|
|
|
CREATE OPERATOR !==== (
|
|
|
|
LEFTARG = boolean,
|
|
|
|
RIGHTARG = real,
|
|
|
|
PROCEDURE = alter_op_test_fn_bool_real
|
|
|
|
);
|
|
|
|
-- No-op setting already false hashes and merges to false works
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (MERGES = false);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (HASHES = false);
|
|
|
|
-- Test setting merges and hashes
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (MERGES);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (HASHES);
|
|
|
|
SELECT oprcanmerge, oprcanhash
|
|
|
|
FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'real'::regtype;
|
|
|
|
oprcanmerge | oprcanhash
|
|
|
|
-------------+------------
|
|
|
|
t | t
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- Test setting commutator
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (COMMUTATOR = ====);
|
|
|
|
-- Check that oprcom has been set on both the operator and commutator,
|
|
|
|
-- that they reference each other, and that the operator used is the existing
|
|
|
|
-- one we created and not a new shell operator.
|
|
|
|
SELECT op.oprname AS operator_name, com.oprname AS commutator_name,
|
|
|
|
com.oprcode AS commutator_func
|
|
|
|
FROM pg_operator op
|
|
|
|
INNER JOIN pg_operator com ON (op.oid = com.oprcom AND op.oprcom = com.oid)
|
|
|
|
WHERE op.oprname = '==='
|
|
|
|
AND op.oprleft = 'boolean'::regtype AND op.oprright = 'real'::regtype;
|
|
|
|
operator_name | commutator_name | commutator_func
|
|
|
|
---------------+-----------------+----------------------------
|
|
|
|
=== | ==== | alter_op_test_fn_real_bool
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- Cannot set self as negator
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (NEGATOR = ===);
|
|
|
|
ERROR: operator cannot be its own negator
|
|
|
|
-- Test setting negator
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (NEGATOR = !====);
|
|
|
|
-- Check that oprnegate has been set on both the operator and negator,
|
|
|
|
-- that they reference each other, and that the operator used is the existing
|
|
|
|
-- one we created and not a new shell operator.
|
|
|
|
SELECT op.oprname AS operator_name, neg.oprname AS negator_name,
|
|
|
|
neg.oprcode AS negator_func
|
|
|
|
FROM pg_operator op
|
|
|
|
INNER JOIN pg_operator neg ON (op.oid = neg.oprnegate AND op.oprnegate = neg.oid)
|
|
|
|
WHERE op.oprname = '==='
|
|
|
|
AND op.oprleft = 'boolean'::regtype AND op.oprright = 'real'::regtype;
|
|
|
|
operator_name | negator_name | negator_func
|
|
|
|
---------------+--------------+----------------------------
|
|
|
|
=== | !==== | alter_op_test_fn_bool_real
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- Test that no-op set succeeds
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (NEGATOR = !====);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (COMMUTATOR = ====);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (MERGES);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (HASHES);
|
|
|
|
-- Check that the final state of the operator is as we expect
|
|
|
|
SELECT oprcanmerge, oprcanhash,
|
|
|
|
pg_describe_object('pg_operator'::regclass, oprcom, 0) AS commutator,
|
|
|
|
pg_describe_object('pg_operator'::regclass, oprnegate, 0) AS negator
|
|
|
|
FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'real'::regtype;
|
|
|
|
oprcanmerge | oprcanhash | commutator | negator
|
|
|
|
-------------+------------+-----------------------------+------------------------------
|
|
|
|
t | t | operator ====(real,boolean) | operator !====(boolean,real)
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- Cannot change commutator, negator, merges, and hashes when already set
|
|
|
|
CREATE OPERATOR @= (
|
|
|
|
LEFTARG = real,
|
|
|
|
RIGHTARG = boolean,
|
|
|
|
PROCEDURE = alter_op_test_fn_real_bool
|
|
|
|
);
|
|
|
|
CREATE OPERATOR @!= (
|
|
|
|
LEFTARG = boolean,
|
|
|
|
RIGHTARG = real,
|
|
|
|
PROCEDURE = alter_op_test_fn_bool_real
|
|
|
|
);
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (COMMUTATOR = @=);
|
|
|
|
ERROR: operator attribute "commutator" cannot be changed if it has already been set
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (NEGATOR = @!=);
|
|
|
|
ERROR: operator attribute "negator" cannot be changed if it has already been set
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (MERGES = false);
|
|
|
|
ERROR: operator attribute "merges" cannot be changed if it has already been set
|
|
|
|
ALTER OPERATOR === (boolean, real) SET (HASHES = false);
|
|
|
|
ERROR: operator attribute "hashes" cannot be changed if it has already been set
|
|
|
|
-- Cannot set an operator that already has a commutator as the commutator
|
|
|
|
ALTER OPERATOR @=(real, boolean) SET (COMMUTATOR = ===);
|
|
|
|
ERROR: commutator operator === is already the commutator of operator ====
|
|
|
|
-- Cannot set an operator that already has a negator as the negator
|
|
|
|
ALTER OPERATOR @!=(boolean, real) SET (NEGATOR = ===);
|
|
|
|
ERROR: negator operator === is already the negator of operator !====
|
|
|
|
-- Check no changes made
|
|
|
|
SELECT oprcanmerge, oprcanhash,
|
|
|
|
pg_describe_object('pg_operator'::regclass, oprcom, 0) AS commutator,
|
|
|
|
pg_describe_object('pg_operator'::regclass, oprnegate, 0) AS negator
|
|
|
|
FROM pg_operator WHERE oprname = '==='
|
|
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'real'::regtype;
|
|
|
|
oprcanmerge | oprcanhash | commutator | negator
|
|
|
|
-------------+------------+-----------------------------+------------------------------
|
|
|
|
t | t | operator ====(real,boolean) | operator !====(boolean,real)
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Clean up
|
|
|
|
--
|
2016-07-18 00:42:31 +02:00
|
|
|
DROP USER regress_alter_op_user;
|
2015-07-14 17:17:55 +02:00
|
|
|
DROP OPERATOR === (boolean, boolean);
|
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 18:28:38 +02:00
|
|
|
DROP OPERATOR === (boolean, real);
|
|
|
|
DROP OPERATOR ==== (real, boolean);
|
|
|
|
DROP OPERATOR !==== (boolean, real);
|
|
|
|
DROP OPERATOR @= (real, boolean);
|
|
|
|
DROP OPERATOR @!= (boolean, real);
|
2015-12-31 23:37:31 +01:00
|
|
|
DROP FUNCTION customcontsel(internal, oid, internal, integer);
|
|
|
|
DROP FUNCTION alter_op_test_fn(boolean, boolean);
|
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 18:28:38 +02:00
|
|
|
DROP FUNCTION alter_op_test_fn_bool_real(boolean, real);
|
|
|
|
DROP FUNCTION alter_op_test_fn_real_bool(real, boolean);
|