#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/guc.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/rel.h"
IndexStmt *stmt = (IndexStmt *) parsetree;
Oid relid;
LOCKMODE lockmode;
- List *inheritors = NIL;
if (stmt->concurrent)
PreventInTransactionBlock(isTopLevel,
* CREATE INDEX on partitioned tables (but not regular
* inherited tables) recurses to partitions, so we must
* 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;
-
- /* already locked by RangeVarGetRelidExtended */
- rel = heap_open(relid, NoLock);
- if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- inheritors = find_all_inheritors(relid, lockmode,
- NULL);
- heap_close(rel, NoLock);
+ ListCell *lc;
+ List *inheritors = NIL;
+
+ inheritors = find_all_inheritors(relid, lockmode, NULL);
+ foreach(lc, inheritors)
+ {
+ char relkind = get_rel_relkind(lfirst_oid(lc));
+
+ 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 ... */
parsetree);
commandCollected = true;
EventTriggerAlterTableEnd();
-
- list_free(inheritors);
}
break;
ERROR: foreign-data wrapper "dummy" has no handler
EXPLAIN SELECT * FROM ft1; -- ERROR
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
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
COMMENT ON FOREIGN TABLE ft1 IS NULL;
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
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
COMMENT ON FOREIGN TABLE ft1 IS NULL;