mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Harden tableam against nonexistant / wrong kind of AMs.
Previously it was allowed to set default_table_access_method to an
empty string. That makes sense for default_tablespace, where that was
copied from, as it signals falling back to the database's default
tablespace. As there is no equivalent for table AMs, forbid that.
Also make sure to throw a usable error when creating a table using an
index AM, by using get_am_type_oid() to implement get_table_am_oid()
instead of a separate copy. Previously we'd error out only later, in
GetTableAmRoutine().
Thirdly remove GetTableAmRoutineByAmId() - it was only used in an
earlier version of 8586bf7ed8
.
Add tests for the above (some for index AMs as well).
This commit is contained in:
@ -3,6 +3,11 @@
|
||||
--
|
||||
-- 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;
|
||||
ERROR: function int4in(internal) does not exist
|
||||
CREATE ACCESS METHOD bogus TYPE INDEX HANDLER heap_tableam_handler;
|
||||
ERROR: function heap_tableam_handler must return type index_am_handler
|
||||
-- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist
|
||||
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
|
||||
ERROR: data type box has no default operator class for access method "gist2"
|
||||
@ -102,8 +107,24 @@ NOTICE: drop cascades to index grect2ind2
|
||||
--
|
||||
-- Test table access methods
|
||||
--
|
||||
-- prevent empty values
|
||||
SET default_table_access_method = '';
|
||||
ERROR: invalid value for parameter "default_table_access_method": ""
|
||||
DETAIL: default_table_access_method may not be empty.
|
||||
-- prevent nonexistant values
|
||||
SET default_table_access_method = 'I do not exist AM';
|
||||
ERROR: invalid value for parameter "default_table_access_method": "I do not exist AM"
|
||||
DETAIL: Table access method "I do not exist AM" does not exist.
|
||||
-- prevent setting it to an index AM
|
||||
SET default_table_access_method = 'btree';
|
||||
ERROR: access method "btree" is not of type TABLE
|
||||
-- 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;
|
||||
ERROR: function int4in(internal) does not exist
|
||||
CREATE ACCESS METHOD bogus TYPE TABLE HANDLER bthandler;
|
||||
ERROR: function bthandler must return type table_am_handler
|
||||
SELECT amname, amhandler, amtype FROM pg_am where amtype = 't' ORDER BY 1, 2;
|
||||
amname | amhandler | amtype
|
||||
--------+----------------------+--------
|
||||
@ -253,6 +274,18 @@ ORDER BY 3, 1, 2;
|
||||
|
||||
-- don't want to keep those tables, nor the default
|
||||
ROLLBACK;
|
||||
-- Third, check that we can neither create a table using a nonexistant
|
||||
-- AM, nor using an index AM
|
||||
CREATE TABLE i_am_a_failure() USING "";
|
||||
ERROR: zero-length delimited identifier at or near """"
|
||||
LINE 1: CREATE TABLE i_am_a_failure() USING "";
|
||||
^
|
||||
CREATE TABLE i_am_a_failure() USING i_do_not_exist_am;
|
||||
ERROR: access method "i_do_not_exist_am" does not exist
|
||||
CREATE TABLE i_am_a_failure() USING "I do not exist AM";
|
||||
ERROR: access method "I do not exist AM" does not exist
|
||||
CREATE TABLE i_am_a_failure() USING "btree";
|
||||
ERROR: access method "btree" is not of type TABLE
|
||||
-- Drop table access method, which fails as objects depends on it
|
||||
DROP ACCESS METHOD heap2;
|
||||
ERROR: cannot drop access method heap2 because other objects depend on it
|
||||
|
@ -520,6 +520,24 @@ WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
|
||||
-----+---------
|
||||
(0 rows)
|
||||
|
||||
-- Indexes should have AMs of type 'i'
|
||||
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
|
||||
FROM pg_class as pc JOIN pg_am AS pa ON (pc.relam = pa.oid)
|
||||
WHERE pc.relkind IN ('i') and
|
||||
pa.amtype != 'i';
|
||||
oid | relname | amname | amtype
|
||||
-----+---------+--------+--------
|
||||
(0 rows)
|
||||
|
||||
-- Tables, matviews etc should have AMs of type 't'
|
||||
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
|
||||
FROM pg_class as pc JOIN pg_am AS pa ON (pc.relam = pa.oid)
|
||||
WHERE pc.relkind IN ('r', 't', 'm') and
|
||||
pa.amtype != 't';
|
||||
oid | relname | amname | amtype
|
||||
-----+---------+--------+--------
|
||||
(0 rows)
|
||||
|
||||
-- **************** pg_attribute ****************
|
||||
-- Look for illegal values in pg_attribute fields
|
||||
SELECT p1.attrelid, p1.attname
|
||||
|
@ -5,6 +5,11 @@
|
||||
-- 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
|
||||
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
|
||||
|
||||
@ -72,11 +77,26 @@ DROP ACCESS METHOD gist2 CASCADE;
|
||||
-- Test table access methods
|
||||
--
|
||||
|
||||
-- prevent empty values
|
||||
SET default_table_access_method = '';
|
||||
|
||||
-- prevent nonexistant 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' ORDER BY 1, 2;
|
||||
|
||||
|
||||
-- First create tables employing the new AM using USING
|
||||
|
||||
-- plain CREATE TABLE
|
||||
@ -178,6 +198,13 @@ ORDER BY 3, 1, 2;
|
||||
-- don't want to keep those tables, nor the default
|
||||
ROLLBACK;
|
||||
|
||||
-- Third, check that we can neither create a table using a nonexistant
|
||||
-- AM, nor using an index AM
|
||||
CREATE TABLE i_am_a_failure() USING "";
|
||||
CREATE TABLE i_am_a_failure() USING i_do_not_exist_am;
|
||||
CREATE TABLE i_am_a_failure() USING "I do not exist AM";
|
||||
CREATE TABLE i_am_a_failure() USING "btree";
|
||||
|
||||
-- Drop table access method, which fails as objects depends on it
|
||||
DROP ACCESS METHOD heap2;
|
||||
|
||||
|
@ -379,6 +379,18 @@ FROM pg_class as p1
|
||||
WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
|
||||
p1.relam != 0;
|
||||
|
||||
-- Indexes should have AMs of type 'i'
|
||||
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
|
||||
FROM pg_class as pc JOIN pg_am AS pa ON (pc.relam = pa.oid)
|
||||
WHERE pc.relkind IN ('i') and
|
||||
pa.amtype != 'i';
|
||||
|
||||
-- Tables, matviews etc should have AMs of type 't'
|
||||
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
|
||||
FROM pg_class as pc JOIN pg_am AS pa ON (pc.relam = pa.oid)
|
||||
WHERE pc.relkind IN ('r', 't', 'm') and
|
||||
pa.amtype != 't';
|
||||
|
||||
-- **************** pg_attribute ****************
|
||||
|
||||
-- Look for illegal values in pg_attribute fields
|
||||
|
Reference in New Issue
Block a user