diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 595760b19f..d0adced270 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -15,7 +15,9 @@ */ #include "postgres.h" +#include "access/table.h" #include "access/transam.h" +#include "catalog/pg_class.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -24,6 +26,8 @@ #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/tlist.h" +#include "parser/parsetree.h" +#include "partitioning/partdesc.h" #include "tcop/utility.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -3018,6 +3022,42 @@ extract_query_dependencies(Node *query, *relationOids = glob.relationOids; *invalItems = glob.invalItems; *hasRowSecurity = glob.dependsOnRole; + + if (glob.partition_directory != NULL) + DestroyPartitionDirectory(glob.partition_directory); +} + +/* + * Recursively adds a table's partitions' OIDs to relationOids. + */ +static void +add_target_partition_oids_recurse(Oid relid, int lockmode, + PlannerGlobal *glob) +{ + Relation rel; + PartitionDesc pdesc; + int i; + + if (glob->partition_directory == NULL) + glob->partition_directory = + CreatePartitionDirectory(CurrentMemoryContext); + + rel = table_open(relid, lockmode); + pdesc = PartitionDirectoryLookup(glob->partition_directory, rel); + + for (i = 0; i < pdesc->nparts; i++) + { + glob->relationOids = lappend_oid(glob->relationOids, pdesc->oids[i]); + + /* + * If the partition may have its own partitions, recurse to add them + * too. + */ + if (!pdesc->is_leaf[i]) + add_target_partition_oids_recurse(pdesc->oids[i], lockmode, glob); + } + + table_close(rel, NoLock); } /* @@ -3069,6 +3109,17 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context) rte->relid); } + if (query->commandType == CMD_INSERT) + { + RangeTblEntry *result_rte = rt_fetch(query->resultRelation, + query->rtable); + + if (result_rte->relkind == RELKIND_PARTITIONED_TABLE) + add_target_partition_oids_recurse(result_rte->relid, + result_rte->rellockmode, + context->glob); + } + /* And recurse into the query's subexpressions */ return query_tree_walker(query, extract_query_dependencies_walker, (void *) context, 0);