Skip to content

Commit 0dab5ef

Browse files
committed
Fix ALTER OPERATOR to update dependencies properly.
Fix an oversight in commit 321eed5: replacing an operator's selectivity functions needs to result in a corresponding update in pg_depend. We have a function that can handle that, but it was not called by AlterOperator(). To fix this without enlarging pg_operator.h's #include list beyond what clients can safely include, split off the function definitions into a new file pg_operator_fn.h, similarly to what we've done for some other catalog header files. It's not entirely clear whether any client-side code needs to include pg_operator.h, but it seems prudent to assume that there is some such code somewhere.
1 parent e5d06f2 commit 0dab5ef

File tree

6 files changed

+163
-42
lines changed

6 files changed

+163
-42
lines changed

src/backend/catalog/pg_operator.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "catalog/objectaccess.h"
2727
#include "catalog/pg_namespace.h"
2828
#include "catalog/pg_operator.h"
29+
#include "catalog/pg_operator_fn.h"
2930
#include "catalog/pg_proc.h"
3031
#include "catalog/pg_type.h"
3132
#include "miscadmin.h"
@@ -61,8 +62,6 @@ static Oid get_other_operator(List *otherOp,
6162
Oid leftTypeId, Oid rightTypeId,
6263
bool isCommutator);
6364

64-
static ObjectAddress makeOperatorDependencies(HeapTuple tuple);
65-
6665

6766
/*
6867
* Check whether a proposed operator name is legal
@@ -270,7 +269,7 @@ OperatorShellMake(const char *operatorName,
270269
CatalogUpdateIndexes(pg_operator_desc, tup);
271270

272271
/* Add dependencies for the entry */
273-
makeOperatorDependencies(tup);
272+
makeOperatorDependencies(tup, false);
274273

275274
heap_freetuple(tup);
276275

@@ -340,6 +339,7 @@ OperatorCreate(const char *operatorName,
340339
{
341340
Relation pg_operator_desc;
342341
HeapTuple tup;
342+
bool isUpdate;
343343
bool nulls[Natts_pg_operator];
344344
bool replaces[Natts_pg_operator];
345345
Datum values[Natts_pg_operator];
@@ -350,7 +350,6 @@ OperatorCreate(const char *operatorName,
350350
negatorId;
351351
bool selfCommutator = false;
352352
NameData oname;
353-
TupleDesc tupDesc;
354353
int i;
355354
ObjectAddress address;
356355

@@ -515,6 +514,8 @@ OperatorCreate(const char *operatorName,
515514
*/
516515
if (operatorObjectId)
517516
{
517+
isUpdate = true;
518+
518519
tup = SearchSysCacheCopy1(OPEROID,
519520
ObjectIdGetDatum(operatorObjectId));
520521
if (!HeapTupleIsValid(tup))
@@ -531,8 +532,10 @@ OperatorCreate(const char *operatorName,
531532
}
532533
else
533534
{
534-
tupDesc = pg_operator_desc->rd_att;
535-
tup = heap_form_tuple(tupDesc, values, nulls);
535+
isUpdate = false;
536+
537+
tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
538+
values, nulls);
536539

537540
operatorObjectId = simple_heap_insert(pg_operator_desc, tup);
538541
}
@@ -541,7 +544,7 @@ OperatorCreate(const char *operatorName,
541544
CatalogUpdateIndexes(pg_operator_desc, tup);
542545

543546
/* Add dependencies for the entry */
544-
address = makeOperatorDependencies(tup);
547+
address = makeOperatorDependencies(tup, isUpdate);
545548

546549
/* Post creation hook for new operator */
547550
InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
@@ -759,14 +762,15 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
759762
}
760763

761764
/*
762-
* Create dependencies for a new operator (either a freshly inserted
763-
* complete operator, a new shell operator, or a just-updated shell).
765+
* Create dependencies for an operator (either a freshly inserted
766+
* complete operator, a new shell operator, a just-updated shell,
767+
* or an operator that's being modified by ALTER OPERATOR).
764768
*
765769
* NB: the OidIsValid tests in this routine are necessary, in case
766770
* the given operator is a shell.
767771
*/
768-
static ObjectAddress
769-
makeOperatorDependencies(HeapTuple tuple)
772+
ObjectAddress
773+
makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
770774
{
771775
Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
772776
ObjectAddress myself,
@@ -777,11 +781,14 @@ makeOperatorDependencies(HeapTuple tuple)
777781
myself.objectSubId = 0;
778782

779783
/*
780-
* In case we are updating a shell, delete any existing entries, except
784+
* If we are updating the operator, delete any existing entries, except
781785
* for extension membership which should remain the same.
782786
*/
783-
deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
784-
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
787+
if (isUpdate)
788+
{
789+
deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
790+
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
791+
}
785792

786793
/* Dependency on namespace */
787794
if (OidIsValid(oper->oprnamespace))

src/backend/commands/operatorcmds.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "catalog/indexing.h"
4141
#include "catalog/objectaccess.h"
4242
#include "catalog/pg_operator.h"
43+
#include "catalog/pg_operator_fn.h"
4344
#include "catalog/pg_type.h"
4445
#include "commands/alter.h"
4546
#include "commands/defrem.h"
@@ -500,9 +501,9 @@ AlterOperator(AlterOperatorStmt *stmt)
500501
simple_heap_update(catalog, &tup->t_self, tup);
501502
CatalogUpdateIndexes(catalog, tup);
502503

503-
InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
504+
address = makeOperatorDependencies(tup, true);
504505

505-
ObjectAddressSet(address, OperatorRelationId, oprId);
506+
InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
506507

507508
heap_close(catalog, NoLock);
508509

src/include/catalog/pg_operator.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
#define PG_OPERATOR_H
2424

2525
#include "catalog/genbki.h"
26-
#include "catalog/objectaddress.h"
27-
#include "nodes/pg_list.h"
2826

2927
/* ----------------
3028
* pg_operator definition. cpp turns this into
@@ -1826,19 +1824,4 @@ DESCR("delete array element");
18261824
DATA(insert OID = 3287 ( "#-" PGNSP PGUID b f f 3802 1009 3802 0 0 jsonb_delete_path - - ));
18271825
DESCR("delete path");
18281826

1829-
/*
1830-
* function prototypes
1831-
*/
1832-
extern ObjectAddress OperatorCreate(const char *operatorName,
1833-
Oid operatorNamespace,
1834-
Oid leftTypeId,
1835-
Oid rightTypeId,
1836-
Oid procedureId,
1837-
List *commutatorName,
1838-
List *negatorName,
1839-
Oid restrictionId,
1840-
Oid joinId,
1841-
bool canMerge,
1842-
bool canHash);
1843-
18441827
#endif /* PG_OPERATOR_H */

src/include/catalog/pg_operator_fn.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pg_operator_fn.h
4+
* prototypes for functions in catalog/pg_operator.c
5+
*
6+
*
7+
* Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
*
10+
* src/include/catalog/pg_operator_fn.h
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
#ifndef PG_OPERATOR_FN_H
15+
#define PG_OPERATOR_FN_H
16+
17+
#include "catalog/objectaddress.h"
18+
#include "nodes/pg_list.h"
19+
20+
extern ObjectAddress OperatorCreate(const char *operatorName,
21+
Oid operatorNamespace,
22+
Oid leftTypeId,
23+
Oid rightTypeId,
24+
Oid procedureId,
25+
List *commutatorName,
26+
List *negatorName,
27+
Oid restrictionId,
28+
Oid joinId,
29+
bool canMerge,
30+
bool canHash);
31+
32+
extern ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate);
33+
34+
#endif /* PG_OPERATOR_FN_H */

src/test/regress/expected/alter_operator.out

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
1-
CREATE OR REPLACE FUNCTION alter_op_test_fn(boolean, boolean)
1+
CREATE FUNCTION alter_op_test_fn(boolean, boolean)
22
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
3+
CREATE FUNCTION customcontsel(internal, oid, internal, integer)
4+
RETURNS float8 AS 'contsel' LANGUAGE internal STABLE STRICT;
35
CREATE OPERATOR === (
46
LEFTARG = boolean,
57
RIGHTARG = boolean,
68
PROCEDURE = alter_op_test_fn,
79
COMMUTATOR = ===,
810
NEGATOR = !==,
9-
RESTRICT = contsel,
11+
RESTRICT = customcontsel,
1012
JOIN = contjoinsel,
1113
HASHES, MERGES
1214
);
15+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
16+
FROM pg_depend
17+
WHERE classid = 'pg_operator'::regclass AND
18+
objid = '===(bool,bool)'::regoperator
19+
ORDER BY 1;
20+
ref | deptype
21+
-------------------------------------------------------+---------
22+
function alter_op_test_fn(boolean,boolean) | n
23+
function customcontsel(internal,oid,internal,integer) | n
24+
schema public | n
25+
(3 rows)
26+
1327
--
1428
-- Reset and set params
1529
--
@@ -22,6 +36,17 @@ SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
2236
- | -
2337
(1 row)
2438

39+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
40+
FROM pg_depend
41+
WHERE classid = 'pg_operator'::regclass AND
42+
objid = '===(bool,bool)'::regoperator
43+
ORDER BY 1;
44+
ref | deptype
45+
--------------------------------------------+---------
46+
function alter_op_test_fn(boolean,boolean) | n
47+
schema public | n
48+
(2 rows)
49+
2550
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel);
2651
ALTER OPERATOR === (boolean, boolean) SET (JOIN = contjoinsel);
2752
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
@@ -31,6 +56,17 @@ SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
3156
contsel | contjoinsel
3257
(1 row)
3358

59+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
60+
FROM pg_depend
61+
WHERE classid = 'pg_operator'::regclass AND
62+
objid = '===(bool,bool)'::regoperator
63+
ORDER BY 1;
64+
ref | deptype
65+
--------------------------------------------+---------
66+
function alter_op_test_fn(boolean,boolean) | n
67+
schema public | n
68+
(2 rows)
69+
3470
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE, JOIN = NONE);
3571
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
3672
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
@@ -39,14 +75,37 @@ SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
3975
- | -
4076
(1 row)
4177

42-
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel, JOIN = contjoinsel);
78+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
79+
FROM pg_depend
80+
WHERE classid = 'pg_operator'::regclass AND
81+
objid = '===(bool,bool)'::regoperator
82+
ORDER BY 1;
83+
ref | deptype
84+
--------------------------------------------+---------
85+
function alter_op_test_fn(boolean,boolean) | n
86+
schema public | n
87+
(2 rows)
88+
89+
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = customcontsel, JOIN = contjoinsel);
4390
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
4491
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
45-
oprrest | oprjoin
46-
---------+-------------
47-
contsel | contjoinsel
92+
oprrest | oprjoin
93+
---------------+-------------
94+
customcontsel | contjoinsel
4895
(1 row)
4996

97+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
98+
FROM pg_depend
99+
WHERE classid = 'pg_operator'::regclass AND
100+
objid = '===(bool,bool)'::regoperator
101+
ORDER BY 1;
102+
ref | deptype
103+
-------------------------------------------------------+---------
104+
function alter_op_test_fn(boolean,boolean) | n
105+
function customcontsel(internal,oid,internal,integer) | n
106+
schema public | n
107+
(3 rows)
108+
50109
--
51110
-- Test invalid options.
52111
--
@@ -73,3 +132,5 @@ ERROR: must be owner of operator ===
73132
RESET SESSION AUTHORIZATION;
74133
DROP USER regtest_alter_user;
75134
DROP OPERATOR === (boolean, boolean);
135+
DROP FUNCTION customcontsel(internal, oid, internal, integer);
136+
DROP FUNCTION alter_op_test_fn(boolean, boolean);

src/test/regress/sql/alter_operator.sql

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
CREATE OR REPLACE FUNCTION alter_op_test_fn(boolean, boolean)
1+
CREATE FUNCTION alter_op_test_fn(boolean, boolean)
22
RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE;
33

4+
CREATE FUNCTION customcontsel(internal, oid, internal, integer)
5+
RETURNS float8 AS 'contsel' LANGUAGE internal STABLE STRICT;
6+
47
CREATE OPERATOR === (
58
LEFTARG = boolean,
69
RIGHTARG = boolean,
710
PROCEDURE = alter_op_test_fn,
811
COMMUTATOR = ===,
912
NEGATOR = !==,
10-
RESTRICT = contsel,
13+
RESTRICT = customcontsel,
1114
JOIN = contjoinsel,
1215
HASHES, MERGES
1316
);
1417

18+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
19+
FROM pg_depend
20+
WHERE classid = 'pg_operator'::regclass AND
21+
objid = '===(bool,bool)'::regoperator
22+
ORDER BY 1;
23+
1524
--
1625
-- Reset and set params
1726
--
@@ -22,22 +31,46 @@ ALTER OPERATOR === (boolean, boolean) SET (JOIN = NONE);
2231
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
2332
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
2433

34+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
35+
FROM pg_depend
36+
WHERE classid = 'pg_operator'::regclass AND
37+
objid = '===(bool,bool)'::regoperator
38+
ORDER BY 1;
39+
2540
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel);
2641
ALTER OPERATOR === (boolean, boolean) SET (JOIN = contjoinsel);
2742

2843
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
2944
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
3045

46+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
47+
FROM pg_depend
48+
WHERE classid = 'pg_operator'::regclass AND
49+
objid = '===(bool,bool)'::regoperator
50+
ORDER BY 1;
51+
3152
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE, JOIN = NONE);
3253

3354
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
3455
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
3556

36-
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel, JOIN = contjoinsel);
57+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
58+
FROM pg_depend
59+
WHERE classid = 'pg_operator'::regclass AND
60+
objid = '===(bool,bool)'::regoperator
61+
ORDER BY 1;
62+
63+
ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = customcontsel, JOIN = contjoinsel);
3764

3865
SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '==='
3966
AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype;
4067

68+
SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype
69+
FROM pg_depend
70+
WHERE classid = 'pg_operator'::regclass AND
71+
objid = '===(bool,bool)'::regoperator
72+
ORDER BY 1;
73+
4174
--
4275
-- Test invalid options.
4376
--
@@ -60,3 +93,5 @@ ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE);
6093
RESET SESSION AUTHORIZATION;
6194
DROP USER regtest_alter_user;
6295
DROP OPERATOR === (boolean, boolean);
96+
DROP FUNCTION customcontsel(internal, oid, internal, integer);
97+
DROP FUNCTION alter_op_test_fn(boolean, boolean);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy