Fix broken dependency-mongering for index operator classes/families.

For a long time, opclasscmds.c explained that "we do not create a
dependency link to the AM [for an opclass or opfamily], because we don't
currently support DROP ACCESS METHOD".  Commit 473b932870 invented
DROP ACCESS METHOD, but it batted only 1 for 2 on adding the dependency
links, and 0 for 2 on updating the comments about the topic.

In passing, undo the same commit's entirely inappropriate decision to
blow away an existing index as a side-effect of create_am.sql.
This commit is contained in:
Tom Lane 2016-04-13 23:33:31 -04:00
parent c8cb745323
commit 92a30a7eb0
4 changed files with 34 additions and 45 deletions

View File

@ -285,14 +285,18 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
heap_freetuple(tup);
/*
* Create dependencies for the opfamily proper. Note: we do not create a
* dependency link to the AM, because we don't currently support DROP
* ACCESS METHOD.
* Create dependencies for the opfamily proper.
*/
myself.classId = OperatorFamilyRelationId;
myself.objectId = opfamilyoid;
myself.objectSubId = 0;
/* dependency on access method */
referenced.classId = AccessMethodRelationId;
referenced.objectId = amoid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
/* dependency on namespace */
referenced.classId = NamespaceRelationId;
referenced.objectId = namespaceoid;
@ -670,20 +674,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
/*
* Create dependencies for the opclass proper. Note: we do not create a
* dependency link to the AM, because we don't currently support DROP
* ACCESS METHOD.
* Create dependencies for the opclass proper. Note: we do not need a
* dependency link to the AM, because that exists through the opfamily.
*/
myself.classId = OperatorClassRelationId;
myself.objectId = opclassoid;
myself.objectSubId = 0;
/* dependency on access method */
referenced.classId = AccessMethodRelationId;
referenced.objectId = amoid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on namespace */
referenced.classId = NamespaceRelationId;
referenced.objectId = namespaceoid;

View File

@ -3,10 +3,8 @@
--
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
-- Drop old index on fast_emp4000
DROP INDEX grect2ind;
-- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist
CREATE INDEX grect2ind ON fast_emp4000 USING gist2 (home_base);
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
ERROR: data type box has no default operator class for access method "gist2"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
-- Make operator class for boxes using gist2
@ -35,8 +33,11 @@ CREATE OPERATOR CLASS box_ops DEFAULT
FUNCTION 7 gist_box_same(box, box, internal),
FUNCTION 9 gist_box_fetch(internal);
-- Create gist2 index on fast_emp4000
CREATE INDEX grect2ind ON fast_emp4000 USING gist2 (home_base);
-- Now check the results from plain indexscan
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
-- Now check the results from plain indexscan; temporarily drop existing
-- index grect2ind to ensure it doesn't capture the plan
BEGIN;
DROP INDEX grect2ind;
SET enable_seqscan = OFF;
SET enable_indexscan = ON;
SET enable_bitmapscan = OFF;
@ -48,7 +49,7 @@ SELECT * FROM fast_emp4000
----------------------------------------------------------------
Sort
Sort Key: ((home_base[0])[0])
-> Index Only Scan using grect2ind on fast_emp4000
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base @ '(2000,1000),(200,200)'::box)
(4 rows)
@ -66,7 +67,7 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
QUERY PLAN
-------------------------------------------------------------
Aggregate
-> Index Only Scan using grect2ind on fast_emp4000
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base && '(1000,1000),(0,0)'::box)
(3 rows)
@ -78,10 +79,10 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
EXPLAIN (COSTS OFF)
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
QUERY PLAN
-------------------------------------------------------
QUERY PLAN
--------------------------------------------------------
Aggregate
-> Index Only Scan using grect2ind on fast_emp4000
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base IS NULL)
(3 rows)
@ -91,18 +92,12 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
278
(1 row)
-- Try to drop access method: fail because of depending objects
ROLLBACK;
-- Try to drop access method: fail because of dependent objects
DROP ACCESS METHOD gist2;
ERROR: cannot drop access method gist2 because other objects depend on it
DETAIL: operator class box_ops for access method gist2 depends on access method gist2
index grect2ind depends on operator class box_ops for access method gist2
DETAIL: index grect2ind2 depends on operator class box_ops for access method gist2
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- Drop access method cascade
DROP ACCESS METHOD gist2 CASCADE;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to operator class box_ops for access method gist2
drop cascades to index grect2ind
-- Reset optimizer options
RESET enable_seqscan;
RESET enable_indexscan;
RESET enable_bitmapscan;
NOTICE: drop cascades to index grect2ind2

View File

@ -44,7 +44,7 @@ e_star|f
emp|f
equipment_r|f
f_star|f
fast_emp4000|f
fast_emp4000|t
float4_tbl|f
float8_tbl|f
func_index_heap|t

View File

@ -5,11 +5,8 @@
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
-- Drop old index on fast_emp4000
DROP INDEX grect2ind;
-- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist
CREATE INDEX grect2ind ON fast_emp4000 USING gist2 (home_base);
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
-- Make operator class for boxes using gist2
CREATE OPERATOR CLASS box_ops DEFAULT
@ -38,9 +35,12 @@ CREATE OPERATOR CLASS box_ops DEFAULT
FUNCTION 9 gist_box_fetch(internal);
-- Create gist2 index on fast_emp4000
CREATE INDEX grect2ind ON fast_emp4000 USING gist2 (home_base);
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
-- Now check the results from plain indexscan
-- Now check the results from plain indexscan; temporarily drop existing
-- index grect2ind to ensure it doesn't capture the plan
BEGIN;
DROP INDEX grect2ind;
SET enable_seqscan = OFF;
SET enable_indexscan = ON;
SET enable_bitmapscan = OFF;
@ -61,13 +61,10 @@ EXPLAIN (COSTS OFF)
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
-- Try to drop access method: fail because of depending objects
ROLLBACK;
-- Try to drop access method: fail because of dependent objects
DROP ACCESS METHOD gist2;
-- Drop access method cascade
DROP ACCESS METHOD gist2 CASCADE;
-- Reset optimizer options
RESET enable_seqscan;
RESET enable_indexscan;
RESET enable_bitmapscan;