mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Don't allow partitioned index on foreign-table partitions
Creating indexes on foreign tables is already forbidden, but local partitioned indexes (commit 8b08f7d4820f) forgot to check for them. Add a preliminary check to prevent wasting time. Another school of thought says to allow the index to be created if it's not a unique index; but it's possible to do better in the future (enable indexing of foreign tables, somehow), so we avoid painting ourselves in a corner by rejecting all cases, to avoid future grief (a.k.a. backward incompatible changes). Reported-by: Arseny Sher Author: Amit Langote, Álvaro Herrera Discussion: https://postgr.es/m/87sh71cakz.fsf@ars-thinkpad
This commit is contained in:
parent
fc2a41e23e
commit
4eaa537275
@ -67,6 +67,7 @@
|
|||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/guc.h"
|
#include "utils/guc.h"
|
||||||
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
|
|
||||||
@ -1287,7 +1288,6 @@ ProcessUtilitySlow(ParseState *pstate,
|
|||||||
IndexStmt *stmt = (IndexStmt *) parsetree;
|
IndexStmt *stmt = (IndexStmt *) parsetree;
|
||||||
Oid relid;
|
Oid relid;
|
||||||
LOCKMODE lockmode;
|
LOCKMODE lockmode;
|
||||||
List *inheritors = NIL;
|
|
||||||
|
|
||||||
if (stmt->concurrent)
|
if (stmt->concurrent)
|
||||||
PreventInTransactionBlock(isTopLevel,
|
PreventInTransactionBlock(isTopLevel,
|
||||||
@ -1314,17 +1314,33 @@ ProcessUtilitySlow(ParseState *pstate,
|
|||||||
* CREATE INDEX on partitioned tables (but not regular
|
* CREATE INDEX on partitioned tables (but not regular
|
||||||
* inherited tables) recurses to partitions, so we must
|
* inherited tables) recurses to partitions, so we must
|
||||||
* acquire locks early to avoid deadlocks.
|
* acquire locks early to avoid deadlocks.
|
||||||
|
*
|
||||||
|
* We also take the opportunity to verify that all
|
||||||
|
* partitions are something we can put an index on,
|
||||||
|
* to avoid building some indexes only to fail later.
|
||||||
*/
|
*/
|
||||||
if (stmt->relation->inh)
|
if (stmt->relation->inh &&
|
||||||
|
get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE)
|
||||||
{
|
{
|
||||||
Relation rel;
|
ListCell *lc;
|
||||||
|
List *inheritors = NIL;
|
||||||
|
|
||||||
/* already locked by RangeVarGetRelidExtended */
|
inheritors = find_all_inheritors(relid, lockmode, NULL);
|
||||||
rel = heap_open(relid, NoLock);
|
foreach(lc, inheritors)
|
||||||
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
{
|
||||||
inheritors = find_all_inheritors(relid, lockmode,
|
char relkind = get_rel_relkind(lfirst_oid(lc));
|
||||||
NULL);
|
|
||||||
heap_close(rel, NoLock);
|
if (relkind != RELKIND_RELATION &&
|
||||||
|
relkind != RELKIND_MATVIEW &&
|
||||||
|
relkind != RELKIND_PARTITIONED_TABLE)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
|
errmsg("cannot create index on partitioned table \"%s\"",
|
||||||
|
stmt->relation->relname),
|
||||||
|
errdetail("Table \"%s\" contains partitions that are foreign tables.",
|
||||||
|
stmt->relation->relname)));
|
||||||
|
}
|
||||||
|
list_free(inheritors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run parse analysis ... */
|
/* Run parse analysis ... */
|
||||||
@ -1353,8 +1369,6 @@ ProcessUtilitySlow(ParseState *pstate,
|
|||||||
parsetree);
|
parsetree);
|
||||||
commandCollected = true;
|
commandCollected = true;
|
||||||
EventTriggerAlterTableEnd();
|
EventTriggerAlterTableEnd();
|
||||||
|
|
||||||
list_free(inheritors);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -749,6 +749,13 @@ SELECT * FROM ft1; -- ERROR
|
|||||||
ERROR: foreign-data wrapper "dummy" has no handler
|
ERROR: foreign-data wrapper "dummy" has no handler
|
||||||
EXPLAIN SELECT * FROM ft1; -- ERROR
|
EXPLAIN SELECT * FROM ft1; -- ERROR
|
||||||
ERROR: foreign-data wrapper "dummy" has no handler
|
ERROR: foreign-data wrapper "dummy" has no handler
|
||||||
|
CREATE TABLE lt1 (a INT) PARTITION BY RANGE (a);
|
||||||
|
CREATE FOREIGN TABLE ft_part1
|
||||||
|
PARTITION OF lt1 FOR VALUES FROM (0) TO (1000) SERVER s0;
|
||||||
|
CREATE INDEX ON lt1 (a); -- ERROR
|
||||||
|
ERROR: cannot create index on partitioned table "lt1"
|
||||||
|
DETAIL: Table "lt1" contains partitions that are foreign tables.
|
||||||
|
DROP TABLE lt1;
|
||||||
-- ALTER FOREIGN TABLE
|
-- ALTER FOREIGN TABLE
|
||||||
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
|
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
|
||||||
COMMENT ON FOREIGN TABLE ft1 IS NULL;
|
COMMENT ON FOREIGN TABLE ft1 IS NULL;
|
||||||
|
@ -316,6 +316,12 @@ CREATE INDEX id_ft1_c2 ON ft1 (c2); -- ERROR
|
|||||||
SELECT * FROM ft1; -- ERROR
|
SELECT * FROM ft1; -- ERROR
|
||||||
EXPLAIN SELECT * FROM ft1; -- ERROR
|
EXPLAIN SELECT * FROM ft1; -- ERROR
|
||||||
|
|
||||||
|
CREATE TABLE lt1 (a INT) PARTITION BY RANGE (a);
|
||||||
|
CREATE FOREIGN TABLE ft_part1
|
||||||
|
PARTITION OF lt1 FOR VALUES FROM (0) TO (1000) SERVER s0;
|
||||||
|
CREATE INDEX ON lt1 (a); -- ERROR
|
||||||
|
DROP TABLE lt1;
|
||||||
|
|
||||||
-- ALTER FOREIGN TABLE
|
-- ALTER FOREIGN TABLE
|
||||||
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
|
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
|
||||||
COMMENT ON FOREIGN TABLE ft1 IS NULL;
|
COMMENT ON FOREIGN TABLE ft1 IS NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user