2727#define PARENTHOOD_TAG CppAsString(PARENTHOOD)
2828
2929
30+ typedef enum
31+ {
32+ FP_FOUND , /* Found partition */
33+ FP_PLAIN_TABLE , /* Table isn't partitioned by pg_pathman */
34+ FP_NON_SINGULAR_RESULT /* Multiple or no partitions */
35+ } FindPartitionResult ;
36+
3037static bool pathman_transform_query_walker (Node * node , void * context );
3138
3239static void disable_standard_inheritance (Query * parse );
@@ -36,7 +43,7 @@ static void partition_filter_visitor(Plan *plan, void *context);
3643
3744static rel_parenthood_status tag_extract_parenthood_status (List * relation_tag );
3845
39- static Oid find_deepest_partition (Oid relid , Index idx , Expr * quals );
46+ static FindPartitionResult find_deepest_partition (Oid relid , Index idx , Expr * quals , Oid * partition );
4047
4148
4249/*
@@ -244,6 +251,7 @@ handle_modification_query(Query *parse)
244251 Expr * quals ;
245252 Index result_rel ;
246253 Oid child ;
254+ FindPartitionResult fp_result ;
247255
248256 /* Fetch index of result relation */
249257 result_rel = parse -> resultRelation ;
@@ -265,13 +273,13 @@ handle_modification_query(Query *parse)
265273 * Parse syntax tree and extract deepest partition (if there is only one
266274 * satisfying quals)
267275 */
268- child = find_deepest_partition (rte -> relid , result_rel , quals );
276+ fp_result = find_deepest_partition (rte -> relid , result_rel , quals , & child );
269277
270278 /*
271279 * If only one partition is affected,
272280 * substitute parent table with partition.
273281 */
274- if (OidIsValid ( child ) )
282+ if (fp_result == FP_FOUND )
275283 {
276284 Relation child_rel ,
277285 parent_rel ;
@@ -333,25 +341,28 @@ handle_modification_query(Query *parse)
333341 * Find a single deepest subpartition. If there are more than one partitions
334342 * satisfies quals or no such partition at all then return InvalidOid.
335343 */
336- static Oid
337- find_deepest_partition (Oid relid , Index idx , Expr * quals )
344+ static FindPartitionResult
345+ find_deepest_partition (Oid relid , Index idx , Expr * quals , Oid * partition )
338346{
339347 const PartRelationInfo * prel ;
340348 Node * prel_expr ;
341349 WalkerContext context ;
342350 List * ranges ;
343351 WrapperNode * wrap ;
344352
345- /* Exit if there's no quals (no use) */
346- if (!quals ) return InvalidOid ;
347-
348353 prel = get_pathman_relation_info (relid );
349354
350355 /* Exit if it's not partitioned */
351- if (!prel ) return InvalidOid ;
356+ if (!prel )
357+ return FP_PLAIN_TABLE ;
352358
353359 /* Exit if we must include parent */
354- if (prel -> enable_parent ) return InvalidOid ;
360+ if (prel -> enable_parent )
361+ return FP_NON_SINGULAR_RESULT ;
362+
363+ /* Exit if there's no quals (no use) */
364+ if (!quals )
365+ return FP_NON_SINGULAR_RESULT ;
355366
356367 /* Prepare partitioning expression */
357368 prel_expr = PrelExpressionForRelid (prel , idx );
@@ -370,21 +381,32 @@ find_deepest_partition(Oid relid, Index idx, Expr *quals)
370381 if (irange_lower (irange ) == irange_upper (irange ))
371382 {
372383 Oid * children = PrelGetChildrenArray (prel ),
373- partition = children [irange_lower (irange )],
384+ child = children [irange_lower (irange )],
374385 subpartition ;
386+ FindPartitionResult result ;
375387
376388 /*
377389 * Try to go deeper and see if there is subpartition
378390 */
379- subpartition = find_deepest_partition (partition , idx , quals );
380- if (OidIsValid (subpartition ))
381- return subpartition ;
382-
383- return partition ;
391+ result = find_deepest_partition (child ,
392+ idx ,
393+ quals ,
394+ & subpartition );
395+ switch (result )
396+ {
397+ case FP_FOUND :
398+ * partition = subpartition ;
399+ return FP_FOUND ;
400+ case FP_PLAIN_TABLE :
401+ * partition = child ;
402+ return FP_FOUND ;
403+ case FP_NON_SINGULAR_RESULT :
404+ return FP_NON_SINGULAR_RESULT ;
405+ }
384406 }
385407 }
386408
387- return InvalidOid ;
409+ return FP_NON_SINGULAR_RESULT ;
388410}
389411
390412/*
0 commit comments