-- Make gist2 over gisthandler. In fact, it would be a synonym to gist. CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
-- Verify return type checks for handlers CREATE ACCESS METHOD bogus TYPE INDEX HANDLER int4in; CREATE ACCESS METHOD bogus TYPE INDEX HANDLER heap_tableam_handler;
-- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist CREATEINDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
-- Make operator class for boxes using gist2 CREATE OPERATOR CLASS box_ops DEFAULT FOR TYPE box USING gist2 AS
OPERATOR 1 <<,
OPERATOR 2 &<,
OPERATOR 3 &&,
OPERATOR 4 &>,
OPERATOR 5 >>,
OPERATOR 6 ~=,
OPERATOR 7 @>,
OPERATOR 8 <@,
OPERATOR 9 &<|,
OPERATOR 10 <<|,
OPERATOR 11 |>>,
OPERATOR 12 |&>,
FUNCTION 1 gist_box_consistent(internal, box, smallint, oid, internal),
FUNCTION 2 gist_box_union(internal, internal), -- don't need compress, decompress, or fetch functions
FUNCTION 5 gist_box_penalty(internal, internal, internal),
FUNCTION 6 gist_box_picksplit(internal, internal),
FUNCTION 7 gist_box_same(box, box, internal);
-- Create gist2 index on fast_emp4000 CREATEINDEX 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; DROPINDEX grect2ind; SET enable_seqscan = OFF; SET enable_indexscan = ON; SET enable_bitmapscan = OFF;
EXPLAIN (COSTS OFF) SELECT * FROM fast_emp4000 WHERE home_base <@ '(200,200),(2000,1000)'::box ORDERBY (home_base[0])[0]; SELECT * FROM fast_emp4000 WHERE home_base <@ '(200,200),(2000,1000)'::box ORDERBY (home_base[0])[0];
EXPLAIN (COSTS OFF) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
EXPLAIN (COSTS OFF) SELECT count(*) FROM fast_emp4000 WHERE home_base ISNULL; SELECT count(*) FROM fast_emp4000 WHERE home_base ISNULL;
ROLLBACK;
-- Try to drop access method: fail because of dependent objects DROP ACCESS METHOD gist2;
-- Drop access method cascade -- To prevent a (rare) deadlock against autovacuum, -- we must lock the table that owns the index that will be dropped
BEGIN; LOCKTABLE fast_emp4000; DROP ACCESS METHOD gist2 CASCADE; COMMIT;
-- -- Test table access methods --
-- prevent empty values SET default_table_access_method = '';
-- prevent nonexistent values SET default_table_access_method = 'I do not exist AM';
-- prevent setting it to an index AM SET default_table_access_method = 'btree';
-- Create a heap2 table am handler with heapam handler CREATE ACCESS METHOD heap2 TYPE TABLE HANDLER heap_tableam_handler;
-- Verify return type checks for handlers CREATE ACCESS METHOD bogus TYPE TABLE HANDLER int4in; CREATE ACCESS METHOD bogus TYPE TABLE HANDLER bthandler;
SELECT amname, amhandler, amtype FROM pg_am where amtype = 't'ORDERBY1, 2;
-- First create tables employing the new AM using USING
-- plain CREATE TABLE CREATETABLE tableam_tbl_heap2(f1 int) USING heap2; INSERTINTO tableam_tbl_heap2 VALUES(1); SELECT f1 FROM tableam_tbl_heap2 ORDERBY f1;
-- CREATE TABLE AS CREATETABLE tableam_tblas_heap2 USING heap2 ASSELECT * FROM tableam_tbl_heap2; SELECT f1 FROM tableam_tbl_heap2 ORDERBY f1;
-- SELECT INTO doesn't support USING SELECTINTO tableam_tblselectinto_heap2 USING heap2 FROM tableam_tbl_heap2;
-- CREATE VIEW doesn't support USING CREATE VIEW tableam_view_heap2 USING heap2 ASSELECT * FROM tableam_tbl_heap2;
-- CREATE SEQUENCE doesn't support USING CREATE SEQUENCE tableam_seq_heap2 USING heap2;
-- CREATE MATERIALIZED VIEW does support USING CREATE MATERIALIZED VIEW tableam_tblmv_heap2 USING heap2 ASSELECT * FROM tableam_tbl_heap2; SELECT f1 FROM tableam_tblmv_heap2 ORDERBY f1;
-- CREATE TABLE .. PARTITION BY supports USING. CREATETABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a) USING heap2; SELECT a.amname FROM pg_class c, pg_am a WHERE c.relname = 'tableam_parted_heap2'AND a.oid = c.relam; DROPTABLE tableam_parted_heap2;
CREATETABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a); -- new partitions will inherit from the current default, rather the partition root SET default_table_access_method = 'heap'; CREATETABLE tableam_parted_a_heap2 PARTITION OF tableam_parted_heap2 FORVALUESIN ('a'); SET default_table_access_method = 'heap2'; CREATETABLE tableam_parted_b_heap2 PARTITION OF tableam_parted_heap2 FORVALUESIN ('b');
RESET default_table_access_method; -- but the method can be explicitly specified CREATETABLE tableam_parted_c_heap2 PARTITION OF tableam_parted_heap2 FORVALUESIN ('c') USING heap; CREATETABLE tableam_parted_d_heap2 PARTITION OF tableam_parted_heap2 FORVALUESIN ('d') USING heap2;
-- List all objects in AM SELECT
pc.relkind,
pa.amname, CASEWHEN relkind = 't'THEN
(SELECT'toast for ' || relname::regclass FROM pg_class pcm WHERE pcm.reltoastrelid = pc.oid) ELSE
relname::regclass::text
END COLLATE"C"AS relname FROM pg_class AS pc,
pg_am AS pa WHERE pa.oid = pc.relam AND pa.amname = 'heap2' ORDERBY3, 1, 2;
-- Show dependencies onto AM - there shouldn't be any for toast SELECT pg_describe_object(classid,objid,objsubid) AS obj FROM pg_depend, pg_am WHERE pg_depend.refclassid = 'pg_am'::regclass AND pg_am.oid = pg_depend.refobjid AND pg_am.amname = 'heap2' ORDERBY classid, objid, objsubid;
-- ALTER TABLE SET ACCESS METHOD CREATETABLE heaptable USING heap AS SELECT a, repeat(a::text, 100) FROM generate_series(1,9) AS a; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass; -- Switching to heap2 adds new dependency entry to the AM. ALTERTABLE heaptable SET ACCESS METHOD heap2; SELECT pg_describe_object(classid, objid, objsubid) as obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as objref,
deptype FROM pg_depend WHERE classid = 'pg_class'::regclass AND
objid = 'heaptable'::regclass ORDERBY1, 2; -- Switching to heap should not have a dependency entry to the AM. ALTERTABLE heaptable SET ACCESS METHOD heap; SELECT pg_describe_object(classid, objid, objsubid) as obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as objref,
deptype FROM pg_depend WHERE classid = 'pg_class'::regclass AND
objid = 'heaptable'::regclass ORDERBY1, 2; ALTERTABLE heaptable SET ACCESS METHOD heap2; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass; SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heaptable; -- DEFAULT access method
BEGIN; SET LOCAL default_table_access_method TO heap2; ALTERTABLE heaptable SET ACCESS METHOD DEFAULT; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass; SET LOCAL default_table_access_method TO heap; ALTERTABLE heaptable SET ACCESS METHOD DEFAULT; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
ROLLBACK; -- ALTER MATERIALIZED VIEW SET ACCESS METHOD CREATE MATERIALIZED VIEW heapmv USING heap ASSELECT * FROM heaptable; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heapmv'::regclass; ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap2; SELECT amname FROM pg_class c, pg_am am WHERE c.relam = am.oid AND c.oid = 'heapmv'::regclass; SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heapmv; -- No support for multiple subcommands ALTERTABLE heaptable SET ACCESS METHOD heap, SET ACCESS METHOD heap2; ALTERTABLE heaptable SET ACCESS METHOD DEFAULT, SET ACCESS METHOD heap2; ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2; DROP MATERIALIZED VIEW heapmv; DROPTABLE heaptable;
-- Partitioned table with USING CREATETABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2; SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj FROM pg_depend, pg_am WHERE pg_depend.refclassid = 'pg_am'::regclass AND pg_am.oid = pg_depend.refobjid AND pg_depend.objid = 'am_partitioned'::regclass; DROPTABLE am_partitioned;
-- Partition hierarchies with access methods
BEGIN; SET LOCAL default_table_access_method = 'heap'; CREATETABLE am_partitioned(x INT, y INT) PARTITION BY hash (x); -- pg_class.relam is 0, no dependency recorded between the AM and the -- partitioned table. SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj FROM pg_depend, pg_am WHERE pg_depend.refclassid = 'pg_am'::regclass AND pg_am.oid = pg_depend.refobjid AND pg_depend.objid = 'am_partitioned'::regclass; -- New default is set, with dependency added. ALTERTABLE am_partitioned SET ACCESS METHOD heap2; SELECT a.amname FROM pg_class c, pg_am a WHERE c.relname = 'am_partitioned'AND a.oid = c.relam; SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj FROM pg_depend, pg_am WHERE pg_depend.refclassid = 'pg_am'::regclass AND pg_am.oid = pg_depend.refobjid AND pg_depend.objid = 'am_partitioned'::regclass; -- Default is set, with dependency updated. SET LOCAL default_table_access_method = 'heap2'; ALTERTABLE am_partitioned SET ACCESS METHOD heap; SELECT a.amname FROM pg_class c, pg_am a WHERE c.relname = 'am_partitioned'AND a.oid = c.relam; -- Dependency pinned, hence removed. SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj FROM pg_depend, pg_am WHERE pg_depend.refclassid = 'pg_am'::regclass AND pg_am.oid = pg_depend.refobjid AND pg_depend.objid = 'am_partitioned'::regclass; -- Default and AM set in the clause are the same, relam should be set. SET LOCAL default_table_access_method = 'heap2'; ALTERTABLE am_partitioned SET ACCESS METHOD heap2; SELECT a.amname FROM pg_class c, pg_am a WHERE c.relname = 'am_partitioned'AND a.oid = c.relam; -- Reset to default ALTERTABLE am_partitioned SET ACCESS METHOD DEFAULT; SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; -- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitions -- will inherit the AM set. Existing partitioned are unchanged. SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; SET LOCAL default_table_access_method = 'heap'; CREATETABLE am_partitioned_0 PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 0); SET LOCAL default_table_access_method = 'heap2'; CREATETABLE am_partitioned_1 PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 1); SET LOCAL default_table_access_method = 'heap'; ALTERTABLE am_partitioned SET ACCESS METHOD heap2; CREATETABLE am_partitioned_2 PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 2); ALTERTABLE am_partitioned SET ACCESS METHOD DEFAULT; SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; CREATETABLE am_partitioned_3 PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 3); -- Partitioned table with relam at 0 ALTERTABLE am_partitioned SET ACCESS METHOD DEFAULT; CREATETABLE am_partitioned_5p PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 5) PARTITION BY hash(y); -- Partitions of this partitioned table inherit default AM at creation -- time. CREATETABLE am_partitioned_5p1 PARTITION OF am_partitioned_5p FORVALUESWITH (MODULUS 10, REMAINDER 1); -- Partitioned table with relam set. ALTERTABLE am_partitioned SET ACCESS METHOD heap2; CREATETABLE am_partitioned_6p PARTITION OF am_partitioned FORVALUESWITH (MODULUS 10, REMAINDER 6) PARTITION BY hash(y); -- Partitions of this partitioned table inherit its AM. CREATETABLE am_partitioned_6p1 PARTITION OF am_partitioned_6p FORVALUESWITH (MODULUS 10, REMAINDER 1); SELECT c.relname, a.amname FROM pg_class c, pg_am a WHERE c.relam = a.oid AND
c.relname LIKE'am_partitioned%' UNIONALL SELECT c.relname, 'default'FROM pg_class c WHERE c.relam = 0 AND c.relname LIKE'am_partitioned%'ORDERBY1; DROPTABLE am_partitioned; COMMIT;
-- Second, create objects in the new AM by changing the default AM
BEGIN; SET LOCAL default_table_access_method = 'heap2';
-- following tests should all respect the default AM CREATETABLE tableam_tbl_heapx(f1 int); CREATETABLE tableam_tblas_heapx ASSELECT * FROM tableam_tbl_heapx; SELECTINTO tableam_tblselectinto_heapx FROM tableam_tbl_heapx; CREATE MATERIALIZED VIEW tableam_tblmv_heapx USING heap2 ASSELECT * FROM tableam_tbl_heapx; CREATETABLE tableam_parted_heapx (a text, b int) PARTITION BY list (a); CREATETABLE tableam_parted_1_heapx PARTITION OF tableam_parted_heapx FORVALUESIN ('a', 'b');
-- but an explicitly set AM overrides it CREATETABLE tableam_parted_2_heapx PARTITION OF tableam_parted_heapx FORVALUESIN ('c', 'd') USING heap;
-- sequences, views and foreign servers shouldn't have an AM CREATE VIEW tableam_view_heapx ASSELECT * FROM tableam_tbl_heapx; CREATE SEQUENCE tableam_seq_heapx; CREATEFOREIGN DATA WRAPPER fdw_heap2 VALIDATOR postgresql_fdw_validator; CREATE SERVER fs_heap2 FOREIGN DATA WRAPPER fdw_heap2 ; CREATEFOREIGNtable tableam_fdw_heapx () SERVER fs_heap2;
-- Verify that new AM was used for tables, matviews, but not for sequences, views and fdws SELECT
pc.relkind,
pa.amname, CASEWHEN relkind = 't'THEN
(SELECT'toast for ' || relname::regclass FROM pg_class pcm WHERE pcm.reltoastrelid = pc.oid) ELSE
relname::regclass::text
END COLLATE"C"AS relname FROM pg_class AS pc LEFTJOIN pg_am AS pa ON (pa.oid = pc.relam) WHERE pc.relname LIKE'tableam_%_heapx' ORDERBY3, 1, 2;
-- don't want to keep those tables, nor the default
ROLLBACK;
-- Third, check that we can neither create a table using a nonexistent -- AM, nor using an index AM CREATETABLE i_am_a_failure() USING""; CREATETABLE i_am_a_failure() USING i_do_not_exist_am; CREATETABLE i_am_a_failure() USING"I do not exist AM"; CREATETABLE i_am_a_failure() USING"btree";
-- Other weird invalid cases that cause problems CREATEFOREIGNTABLE fp PARTITION OF tableam_parted_a_heap2 DEFAULT SERVER x;
-- Drop table access method, which fails as objects depends on it DROP ACCESS METHOD heap2;
-- we intentionally leave the objects created above alive, to verify pg_dump support
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.