Skip to content

Commit 1f9cc96

Browse files
committed
introduce safe function PrelLastChild(), fixes for get_range_by_idx()
1 parent a2c30a5 commit 1f9cc96

File tree

5 files changed

+42
-31
lines changed

5 files changed

+42
-31
lines changed

src/hooks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
227227
rte->inh = true; /* we must restore 'inh' flag! */
228228

229229
children = PrelGetChildrenArray(prel);
230-
ranges = list_make1_irange(make_irange(0, PrelChildrenCount(prel) - 1, false));
230+
ranges = list_make1_irange(make_irange(0, PrelLastChild(prel), false));
231231

232232
/* Make wrappers over restrictions and collect final rangeset */
233233
InitWalkerContext(&context, prel, NULL, false);

src/nodes_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ rescan_append_common(CustomScanState *node)
502502
Assert(prel);
503503

504504
/* First we select all available partitions... */
505-
ranges = list_make1_irange(make_irange(0, PrelChildrenCount(prel) - 1, false));
505+
ranges = list_make1_irange(make_irange(0, PrelLastChild(prel), false));
506506

507507
InitWalkerContext(&scan_state->wcxt, prel, econtext, false);
508508
foreach (lc, scan_state->custom_exprs)

src/pg_pathman.c

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ handle_modification_query(Query *parse)
320320
return;
321321

322322
/* Parse syntax tree and extract partition ranges */
323-
ranges = list_make1_irange(make_irange(0, PrelChildrenCount(prel) - 1, false));
323+
ranges = list_make1_irange(make_irange(0, PrelLastChild(prel), false));
324324
expr = (Expr *) eval_const_expressions(NULL, parse->jointree->quals);
325325
if (!expr)
326326
return;
@@ -680,7 +680,7 @@ walk_expr_tree(Expr *expr, WalkerContext *context)
680680
result->orig = (const Node *) expr;
681681
result->args = NIL;
682682
result->rangeset = list_make1_irange(
683-
make_irange(0, PrelChildrenCount(context->prel) - 1, true));
683+
make_irange(0, PrelLastChild(context->prel), true));
684684
result->paramsel = 1.0;
685685
return result;
686686
}
@@ -839,7 +839,7 @@ create_partitions_internal(Oid relid, Datum value, Oid value_type)
839839

840840
/* Read max & min range values from PartRelationInfo */
841841
min_rvalue = prel->ranges[0].min;
842-
max_rvalue = prel->ranges[PrelChildrenCount(prel) - 1].max;
842+
max_rvalue = prel->ranges[PrelLastChild(prel)].max;
843843

844844
/* If this is a *date type*, cast 'range_interval' to INTERVAL */
845845
if (is_date_type_internal(value_type))
@@ -1183,9 +1183,7 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
11831183
elog(ERROR, "Unknown partitioning type %u", prel->parttype);
11841184
}
11851185

1186-
result->rangeset = list_make1_irange(make_irange(0,
1187-
PrelChildrenCount(prel) - 1,
1188-
true));
1186+
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
11891187
result->paramsel = 1.0;
11901188
}
11911189

@@ -1211,9 +1209,7 @@ handle_binary_opexpr_param(const PartRelationInfo *prel,
12111209
tce = lookup_type_cache(vartype, TYPECACHE_BTREE_OPFAMILY);
12121210
strategy = get_op_opfamily_strategy(expr->opno, tce->btree_opf);
12131211

1214-
result->rangeset = list_make1_irange(make_irange(0,
1215-
PrelChildrenCount(prel) - 1,
1216-
true));
1212+
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
12171213

12181214
if (strategy == BTEqualStrategyNumber)
12191215
{
@@ -1311,7 +1307,7 @@ handle_const(const Const *c, WalkerContext *context)
13111307
if (!context->for_insert)
13121308
{
13131309
result->rangeset = list_make1_irange(make_irange(0,
1314-
PrelChildrenCount(prel) - 1,
1310+
PrelLastChild(prel),
13151311
true));
13161312
result->paramsel = 1.0;
13171313

@@ -1382,9 +1378,7 @@ handle_opexpr(const OpExpr *expr, WalkerContext *context)
13821378
}
13831379
}
13841380

1385-
result->rangeset = list_make1_irange(make_irange(0,
1386-
PrelChildrenCount(prel) - 1,
1387-
true));
1381+
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
13881382
result->paramsel = 1.0;
13891383
return result;
13901384
}
@@ -1456,7 +1450,7 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
14561450

14571451
if (expr->boolop == AND_EXPR)
14581452
result->rangeset = list_make1_irange(make_irange(0,
1459-
PrelChildrenCount(prel) - 1,
1453+
PrelLastChild(prel),
14601454
false));
14611455
else
14621456
result->rangeset = NIL;
@@ -1479,7 +1473,7 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
14791473
break;
14801474
default:
14811475
result->rangeset = list_make1_irange(make_irange(0,
1482-
PrelChildrenCount(prel) - 1,
1476+
PrelLastChild(prel),
14831477
false));
14841478
break;
14851479
}
@@ -1581,9 +1575,7 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
15811575
result->paramsel = DEFAULT_INEQ_SEL;
15821576

15831577
handle_arrexpr_return:
1584-
result->rangeset = list_make1_irange(make_irange(0,
1585-
PrelChildrenCount(prel) - 1,
1586-
true));
1578+
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
15871579
return result;
15881580
}
15891581

src/pl_funcs.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "pathman.h"
1212
#include "init.h"
1313
#include "utils.h"
14+
#include "relation_info.h"
1415

1516
#include "access/htup_details.h"
1617
#include "access/nbtree.h"
@@ -289,17 +290,23 @@ get_range_by_idx(PG_FUNCTION_ARGS)
289290
prel = get_pathman_relation_info(parent_oid);
290291
shout_if_prel_is_invalid(parent_oid, prel, PT_RANGE);
291292

292-
if (((uint32) abs(idx)) >= PrelChildrenCount(prel))
293+
/* Now we have to deal with 'idx' */
294+
if (idx < -1)
295+
{
296+
elog(ERROR, "Negative indices other than -1 (last partition) are not allowed");
297+
}
298+
else if (idx == -1 && PrelChildrenCount(prel) > 0)
299+
{
300+
idx = PrelLastChild(prel);
301+
}
302+
else if (((uint32) abs(idx)) >= PrelChildrenCount(prel))
303+
{
293304
elog(ERROR, "Partition #%d does not exist (total amount is %u)",
294305
idx, PrelChildrenCount(prel));
306+
}
295307

296308
ranges = PrelGetRangesArray(prel);
297309

298-
if (idx == -1)
299-
idx = PrelChildrenCount(prel) - 1;
300-
else if (idx < -1)
301-
elog(ERROR, "Negative indices other than -1 (last partition) are not allowed");
302-
303310
elems[0] = ranges[idx].min;
304311
elems[1] = ranges[idx].max;
305312

@@ -343,7 +350,7 @@ get_max_range_value(PG_FUNCTION_ARGS)
343350

344351
ranges = PrelGetRangesArray(prel);
345352

346-
PG_RETURN_DATUM(ranges[PrelChildrenCount(prel) - 1].max);
353+
PG_RETURN_DATUM(ranges[PrelLastChild(prel)].max);
347354
}
348355

349356
/*

src/relation_info.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,25 @@ typedef enum
107107
* PartRelationInfo field access macros.
108108
*/
109109

110-
#define PrelGetChildrenArray(prel) ( (prel)->children )
110+
#define PrelGetChildrenArray(prel) ( (prel)->children )
111111

112-
#define PrelGetRangesArray(prel) ( (prel)->ranges )
112+
#define PrelGetRangesArray(prel) ( (prel)->ranges )
113113

114-
#define PrelChildrenCount(prel) ( (prel)->children_count )
114+
#define PrelChildrenCount(prel) ( (prel)->children_count )
115115

116-
#define PrelIsValid(prel) ( (prel) && (prel)->valid )
116+
#define PrelIsValid(prel) ( (prel) && (prel)->valid )
117+
118+
inline static uint32
119+
PrelLastChild(const PartRelationInfo *prel)
120+
{
121+
Assert(PrelIsValid(prel));
122+
123+
if (PrelChildrenCount(prel) == 0)
124+
elog(ERROR, "pg_pathman's cache entry for relation %u has 0 children",
125+
prel->key);
126+
127+
return PrelChildrenCount(prel) - 1; /* last partition */
128+
}
117129

118130

119131
const PartRelationInfo *refresh_pathman_relation_info(Oid relid,

0 commit comments

Comments
 (0)