268 lines
11 KiB
Plaintext
268 lines
11 KiB
Plaintext
CREATE FUNCTION alter_op_test_fn(boolean, boolean)
|
|
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
|
|
CREATE FUNCTION customcontsel(internal, oid, internal, integer)
|
|
RETURNS float8 AS 'contsel' LANGUAGE internal STABLE STRICT;
|
|
CREATE OPERATOR === (
|
|
LEFTARG = boolean,
|
|
RIGHTARG = boolean,
|
|
PROCEDURE = alter_op_test_fn,
|
|
COMMUTATOR = ===,
|
|
NEGATOR = !==,
|
|
RESTRICT = customcontsel,
|
|
JOIN = contjoinsel,
|
|
HASHES, MERGES
|
|
);
|
|
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)
|
|
|
|
--
|
|
-- Test resetting and setting restrict and join attributes.
|
|
--
|
|
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)
|
|
|
|
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 = 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)
|
|
|
|
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 = NONE, JOIN = NONE);
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
|
oprrest | oprjoin
|
|
---------+---------
|
|
- | -
|
|
(1 row)
|
|
|
|
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);
|
|
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
|
|
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
|
|
oprrest | oprjoin
|
|
---------------+-------------
|
|
customcontsel | contjoinsel
|
|
(1 row)
|
|
|
|
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)
|
|
|
|
--
|
|
-- 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
|
|
-- invalid: non-lowercase quoted identifiers
|
|
ALTER OPERATOR & (bit, bit) SET ("Restrict" = _int_contsel, "Join" = _int_contjoinsel);
|
|
ERROR: operator attribute "Restrict" not recognized
|
|
--
|
|
-- Test permission check. Must be owner to ALTER OPERATOR.
|
|
--
|
|
CREATE USER regress_alter_op_user;
|
|
SET SESSION AUTHORIZATION regress_alter_op_user;
|
|
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
|
|
ERROR: must be owner of operator ===
|
|
RESET SESSION AUTHORIZATION;
|
|
--
|
|
-- 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
|
|
--
|
|
DROP USER regress_alter_op_user;
|
|
DROP OPERATOR === (boolean, boolean);
|
|
DROP OPERATOR === (boolean, real);
|
|
DROP OPERATOR ==== (real, boolean);
|
|
DROP OPERATOR !==== (boolean, real);
|
|
DROP OPERATOR @= (real, boolean);
|
|
DROP OPERATOR @!= (boolean, real);
|
|
DROP FUNCTION customcontsel(internal, oid, internal, integer);
|
|
DROP FUNCTION alter_op_test_fn(boolean, boolean);
|
|
DROP FUNCTION alter_op_test_fn_bool_real(boolean, real);
|
|
DROP FUNCTION alter_op_test_fn_real_bool(real, boolean);
|