
In-core relation options can use a custom lock mode since 47167b7, that has lowered the lock available for some autovacuum parameters. However it forgot to consider custom relation options. This causes failures with ALTER TABLE SET when changing a custom relation option, as its lock is not defined. The existing APIs to define a custom reloption does not allow to define a custom lock mode, so enforce its initialization to AccessExclusiveMode which should be safe enough in all cases. An upcoming patch will extend the existing APIs to allow a custom lock mode to be defined. The problem can be reproduced with bloom indexes, so add a test there. Reported-by: Nikolay Sharplov Analyzed-by: Thomas Munro, Michael Paquier Author: Michael Paquier Reviewed-by: Kuntal Ghosh Discussion: https://postgr.es/m/20190920013831.GD1844@paquier.xyz Backpatch-through: 9.6
231 lines
5.1 KiB
Plaintext
231 lines
5.1 KiB
Plaintext
CREATE EXTENSION bloom;
|
|
CREATE TABLE tst (
|
|
i int4,
|
|
t text
|
|
);
|
|
INSERT INTO tst SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
|
|
CREATE INDEX bloomidx ON tst USING bloom (i, t) WITH (col1 = 3);
|
|
ALTER INDEX bloomidx SET (length=80);
|
|
SET enable_seqscan=on;
|
|
SET enable_bitmapscan=off;
|
|
SET enable_indexscan=off;
|
|
SELECT count(*) FROM tst WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
SET enable_seqscan=off;
|
|
SET enable_bitmapscan=on;
|
|
SET enable_indexscan=on;
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tst WHERE i = 7;
|
|
QUERY PLAN
|
|
-------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tst
|
|
Recheck Cond: (i = 7)
|
|
-> Bitmap Index Scan on bloomidx
|
|
Index Cond: (i = 7)
|
|
(5 rows)
|
|
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tst WHERE t = '5';
|
|
QUERY PLAN
|
|
-------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tst
|
|
Recheck Cond: (t = '5'::text)
|
|
-> Bitmap Index Scan on bloomidx
|
|
Index Cond: (t = '5'::text)
|
|
(5 rows)
|
|
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
QUERY PLAN
|
|
---------------------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tst
|
|
Recheck Cond: ((i = 7) AND (t = '5'::text))
|
|
-> Bitmap Index Scan on bloomidx
|
|
Index Cond: ((i = 7) AND (t = '5'::text))
|
|
(5 rows)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
DELETE FROM tst;
|
|
INSERT INTO tst SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
|
|
VACUUM ANALYZE tst;
|
|
SELECT count(*) FROM tst WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
DELETE FROM tst WHERE i > 1 OR t = '5';
|
|
VACUUM tst;
|
|
INSERT INTO tst SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
|
|
SELECT count(*) FROM tst WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
VACUUM FULL tst;
|
|
SELECT count(*) FROM tst WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tst WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
-- Try an unlogged table too
|
|
CREATE UNLOGGED TABLE tstu (
|
|
i int4,
|
|
t text
|
|
);
|
|
INSERT INTO tstu SELECT i%10, substr(md5(i::text), 1, 1) FROM generate_series(1,2000) i;
|
|
CREATE INDEX bloomidxu ON tstu USING bloom (i, t) WITH (col2 = 4);
|
|
SET enable_seqscan=off;
|
|
SET enable_bitmapscan=on;
|
|
SET enable_indexscan=on;
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7;
|
|
QUERY PLAN
|
|
--------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tstu
|
|
Recheck Cond: (i = 7)
|
|
-> Bitmap Index Scan on bloomidxu
|
|
Index Cond: (i = 7)
|
|
(5 rows)
|
|
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE t = '5';
|
|
QUERY PLAN
|
|
--------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tstu
|
|
Recheck Cond: (t = '5'::text)
|
|
-> Bitmap Index Scan on bloomidxu
|
|
Index Cond: (t = '5'::text)
|
|
(5 rows)
|
|
|
|
EXPLAIN (COSTS OFF) SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
|
|
QUERY PLAN
|
|
---------------------------------------------------------
|
|
Aggregate
|
|
-> Bitmap Heap Scan on tstu
|
|
Recheck Cond: ((i = 7) AND (t = '5'::text))
|
|
-> Bitmap Index Scan on bloomidxu
|
|
Index Cond: ((i = 7) AND (t = '5'::text))
|
|
(5 rows)
|
|
|
|
SELECT count(*) FROM tstu WHERE i = 7;
|
|
count
|
|
-------
|
|
200
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tstu WHERE t = '5';
|
|
count
|
|
-------
|
|
112
|
|
(1 row)
|
|
|
|
SELECT count(*) FROM tstu WHERE i = 7 AND t = '5';
|
|
count
|
|
-------
|
|
13
|
|
(1 row)
|
|
|
|
RESET enable_seqscan;
|
|
RESET enable_bitmapscan;
|
|
RESET enable_indexscan;
|
|
-- Run amvalidator function on our opclasses
|
|
SELECT opcname, amvalidate(opc.oid)
|
|
FROM pg_opclass opc JOIN pg_am am ON am.oid = opcmethod
|
|
WHERE amname = 'bloom'
|
|
ORDER BY 1;
|
|
opcname | amvalidate
|
|
----------+------------
|
|
int4_ops | t
|
|
text_ops | t
|
|
(2 rows)
|
|
|
|
--
|
|
-- relation options
|
|
--
|
|
DROP INDEX bloomidx;
|
|
CREATE INDEX bloomidx ON tst USING bloom (i, t) WITH (length=7, col1=4);
|
|
SELECT reloptions FROM pg_class WHERE oid = 'bloomidx'::regclass;
|
|
reloptions
|
|
-------------------
|
|
{length=7,col1=4}
|
|
(1 row)
|
|
|
|
-- check for min and max values
|
|
\set VERBOSITY terse
|
|
CREATE INDEX bloomidx2 ON tst USING bloom (i, t) WITH (length=0);
|
|
ERROR: value 0 out of bounds for option "length"
|
|
CREATE INDEX bloomidx2 ON tst USING bloom (i, t) WITH (col1=0);
|
|
ERROR: value 0 out of bounds for option "col1"
|