Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+21-14
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

+3-2
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

-17
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

+34
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

+67-6
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

+38-3
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)