Hi everyone,
Looks like "sql_inheritance" GUC is affecting partitioned tables:
explain (costs off) select * from test;
QUERY PLAN
------------------------------
Append
-> Seq Scan on test
-> Seq Scan on test_1
-> Seq Scan on test_2
-> Seq Scan on test_1_1
-> Seq Scan on test_1_2
-> Seq Scan on test_1_1_1
-> Seq Scan on test_1_2_1
(8 rows)
set sql_inheritance = off;
explain (costs off) select * from test;
QUERY PLAN
------------------
Seq Scan on test
(1 row)
I might be wrong, but IMO this should not happen. Queries involving update,
delete etc on partitioned tables are basically broken. Moreover, there's no
point in performing such operations on a parent table that's supposed to be
empty at all times.
I've come up with a patch which fixes this behavior for UPDATE, DELETE,
TRUNCATE and also in transformTableEntry(). It might be hacky, but it gives
an idea.
I didn't touch RenameConstraint() and renameatt() since this would break
ALTER TABLE ONLY command.
--
Dmitry Ivanov
Postgres Professional: http://www.postgrespro.com
Russian Postgres Company
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7a574dc..67e118e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1183,7 +1183,7 @@ ExecuteTruncate(TruncateStmt *stmt)
{
RangeVar *rv = lfirst(cell);
Relation rel;
- bool recurse = interpretInhOption(rv->inhOpt);
+ bool recurse;
Oid myrelid;
rel = heap_openrv(rv, AccessExclusiveLock);
@@ -1198,6 +1198,12 @@ ExecuteTruncate(TruncateStmt *stmt)
rels = lappend(rels, rel);
relids = lappend_oid(relids, myrelid);
+ /* Use interpretInhOption() unless it's a partitioned table */
+ if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ recurse = interpretInhOption(rv->inhOpt);
+ else
+ recurse = true;
+
if (recurse)
{
ListCell *child;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 5e65fe7..a3772f7 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -367,6 +367,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Query *qry = makeNode(Query);
ParseNamespaceItem *nsitem;
Node *qual;
+ RangeTblEntry *rte;
qry->commandType = CMD_DELETE;
@@ -384,6 +385,11 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
true,
ACL_DELETE);
+ /* Set "inh" if table is partitioned */
+ rte = rt_fetch(qry->resultRelation, pstate->p_rtable);
+ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ rte->inh = true;
+
/* grab the namespace item made by setTargetTable */
nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
@@ -2164,6 +2170,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Query *qry = makeNode(Query);
ParseNamespaceItem *nsitem;
Node *qual;
+ RangeTblEntry *rte;
qry->commandType = CMD_UPDATE;
pstate->p_is_insert = false;
@@ -2181,6 +2188,11 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
true,
ACL_UPDATE);
+ /* Set "inh" if table is partitioned */
+ rte = rt_fetch(qry->resultRelation, pstate->p_rtable);
+ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ rte->inh = true;
+
/* grab the namespace item made by setTargetTable */
nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 751de4b..215ec73 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -439,6 +439,10 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
rte = addRangeTableEntry(pstate, r, r->alias,
interpretInhOption(r->inhOpt), true);
+ /* Set "inh" if table is partitioned */
+ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ rte->inh = true;
+
return rte;
}
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers