1
0
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:
Andres Freund
2019-04-04 17:17:50 -07:00
parent 344b7e11bb
commit ea97e440b8
9 changed files with 119 additions and 110 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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