mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
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 473b93287040b200 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:
parent
c8cb745323
commit
92a30a7eb0
@ -285,14 +285,18 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
|
|||||||
heap_freetuple(tup);
|
heap_freetuple(tup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create dependencies for the opfamily proper. Note: we do not create a
|
* Create dependencies for the opfamily proper.
|
||||||
* dependency link to the AM, because we don't currently support DROP
|
|
||||||
* ACCESS METHOD.
|
|
||||||
*/
|
*/
|
||||||
myself.classId = OperatorFamilyRelationId;
|
myself.classId = OperatorFamilyRelationId;
|
||||||
myself.objectId = opfamilyoid;
|
myself.objectId = opfamilyoid;
|
||||||
myself.objectSubId = 0;
|
myself.objectSubId = 0;
|
||||||
|
|
||||||
|
/* dependency on access method */
|
||||||
|
referenced.classId = AccessMethodRelationId;
|
||||||
|
referenced.objectId = amoid;
|
||||||
|
referenced.objectSubId = 0;
|
||||||
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
|
||||||
|
|
||||||
/* dependency on namespace */
|
/* dependency on namespace */
|
||||||
referenced.classId = NamespaceRelationId;
|
referenced.classId = NamespaceRelationId;
|
||||||
referenced.objectId = namespaceoid;
|
referenced.objectId = namespaceoid;
|
||||||
@ -670,20 +674,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
|||||||
EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
|
EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create dependencies for the opclass proper. Note: we do not create a
|
* Create dependencies for the opclass proper. Note: we do not need a
|
||||||
* dependency link to the AM, because we don't currently support DROP
|
* dependency link to the AM, because that exists through the opfamily.
|
||||||
* ACCESS METHOD.
|
|
||||||
*/
|
*/
|
||||||
myself.classId = OperatorClassRelationId;
|
myself.classId = OperatorClassRelationId;
|
||||||
myself.objectId = opclassoid;
|
myself.objectId = opclassoid;
|
||||||
myself.objectSubId = 0;
|
myself.objectSubId = 0;
|
||||||
|
|
||||||
/* dependency on access method */
|
|
||||||
referenced.classId = AccessMethodRelationId;
|
|
||||||
referenced.objectId = amoid;
|
|
||||||
referenced.objectSubId = 0;
|
|
||||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
|
||||||
|
|
||||||
/* dependency on namespace */
|
/* dependency on namespace */
|
||||||
referenced.classId = NamespaceRelationId;
|
referenced.classId = NamespaceRelationId;
|
||||||
referenced.objectId = namespaceoid;
|
referenced.objectId = namespaceoid;
|
||||||
|
@ -3,10 +3,8 @@
|
|||||||
--
|
--
|
||||||
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
|
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
|
||||||
CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
|
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
|
-- 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"
|
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.
|
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
|
-- 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 7 gist_box_same(box, box, internal),
|
||||||
FUNCTION 9 gist_box_fetch(internal);
|
FUNCTION 9 gist_box_fetch(internal);
|
||||||
-- Create gist2 index on fast_emp4000
|
-- 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_seqscan = OFF;
|
||||||
SET enable_indexscan = ON;
|
SET enable_indexscan = ON;
|
||||||
SET enable_bitmapscan = OFF;
|
SET enable_bitmapscan = OFF;
|
||||||
@ -48,7 +49,7 @@ SELECT * FROM fast_emp4000
|
|||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
Sort
|
Sort
|
||||||
Sort Key: ((home_base[0])[0])
|
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)
|
Index Cond: (home_base @ '(2000,1000),(200,200)'::box)
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
|||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
Aggregate
|
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)
|
Index Cond: (home_base && '(1000,1000),(0,0)'::box)
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
@ -78,10 +79,10 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
|||||||
|
|
||||||
EXPLAIN (COSTS OFF)
|
EXPLAIN (COSTS OFF)
|
||||||
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
|
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
-------------------------------------------------------
|
--------------------------------------------------------
|
||||||
Aggregate
|
Aggregate
|
||||||
-> Index Only Scan using grect2ind on fast_emp4000
|
-> Index Only Scan using grect2ind2 on fast_emp4000
|
||||||
Index Cond: (home_base IS NULL)
|
Index Cond: (home_base IS NULL)
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
@ -91,18 +92,12 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
|
|||||||
278
|
278
|
||||||
(1 row)
|
(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;
|
DROP ACCESS METHOD gist2;
|
||||||
ERROR: cannot drop access method gist2 because other objects depend on it
|
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
|
DETAIL: index grect2ind2 depends on operator class box_ops for access method gist2
|
||||||
index grect2ind depends on operator class box_ops for access method gist2
|
|
||||||
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
||||||
-- Drop access method cascade
|
-- Drop access method cascade
|
||||||
DROP ACCESS METHOD gist2 CASCADE;
|
DROP ACCESS METHOD gist2 CASCADE;
|
||||||
NOTICE: drop cascades to 2 other objects
|
NOTICE: drop cascades to index grect2ind2
|
||||||
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;
|
|
||||||
|
@ -44,7 +44,7 @@ e_star|f
|
|||||||
emp|f
|
emp|f
|
||||||
equipment_r|f
|
equipment_r|f
|
||||||
f_star|f
|
f_star|f
|
||||||
fast_emp4000|f
|
fast_emp4000|t
|
||||||
float4_tbl|f
|
float4_tbl|f
|
||||||
float8_tbl|f
|
float8_tbl|f
|
||||||
func_index_heap|t
|
func_index_heap|t
|
||||||
|
@ -5,11 +5,8 @@
|
|||||||
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
|
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
|
||||||
CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
|
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
|
-- 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
|
-- Make operator class for boxes using gist2
|
||||||
CREATE OPERATOR CLASS box_ops DEFAULT
|
CREATE OPERATOR CLASS box_ops DEFAULT
|
||||||
@ -38,9 +35,12 @@ CREATE OPERATOR CLASS box_ops DEFAULT
|
|||||||
FUNCTION 9 gist_box_fetch(internal);
|
FUNCTION 9 gist_box_fetch(internal);
|
||||||
|
|
||||||
-- Create gist2 index on fast_emp4000
|
-- 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_seqscan = OFF;
|
||||||
SET enable_indexscan = ON;
|
SET enable_indexscan = ON;
|
||||||
SET enable_bitmapscan = OFF;
|
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;
|
||||||
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 gist2;
|
||||||
|
|
||||||
-- Drop access method cascade
|
-- Drop access method cascade
|
||||||
DROP ACCESS METHOD gist2 CASCADE;
|
DROP ACCESS METHOD gist2 CASCADE;
|
||||||
|
|
||||||
-- Reset optimizer options
|
|
||||||
RESET enable_seqscan;
|
|
||||||
RESET enable_indexscan;
|
|
||||||
RESET enable_bitmapscan;
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user