Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 76a3df6

Browse files
committed
Code review focused on new node types added by partitioning support.
Fix failure to check that we got a plain Const from const-simplification of a coercion request. This is the cause of bug #14666 from Tian Bing: there is an int4 to money cast, but it's only stable not immutable (because of dependence on lc_monetary), resulting in a FuncExpr that the code was miserably unequipped to deal with, or indeed even to notice that it was failing to deal with. Add test cases around this coercion behavior. In view of the above, sprinkle the code liberally with castNode() macros, in hope of catching the next such bug a bit sooner. Also, change some functions that were randomly declared to take Node* to take more specific pointer types. And change some struct fields that were declared Node* but could be given more specific types, allowing removal of assorted explicit casts. Place PARTITION_MAX_KEYS check a bit closer to the code it's protecting. Likewise check only-one-key-for-list-partitioning restriction in a less random place. Avoid not-per-project-style usages like !strcmp(...). Fix assorted failures to avoid scribbling on the input of parse transformation. I'm not sure how necessary this is, but it's entirely silly for these functions to be expending cycles to avoid that and not getting it right. Add guards against partitioning on system columns. Put backend/nodes/ support code into an order that matches handling of these node types elsewhere. Annotate the fact that somebody added location fields to PartitionBoundSpec and PartitionRangeDatum but forgot to handle them in outfuncs.c/readfuncs.c. This is fairly harmless for production purposes (since readfuncs.c would just substitute -1 anyway) but it's still bogus. It's not worth forcing a post-beta1 initdb just to fix this, but if we have another reason to force initdb before 10.0, we should go back and clean this up. Contrariwise, somebody added location fields to PartitionElem and PartitionSpec but forgot to teach exprLocation() about them. Consolidate duplicative code in transformPartitionBound(). Improve a couple of error messages. Improve assorted commentary. Re-pgindent the files touched by this patch; this affects a few comment blocks that must have been added quite recently. Report: https://postgr.es/m/[email protected]
1 parent 54bb322 commit 76a3df6

File tree

18 files changed

+361
-270
lines changed

18 files changed

+361
-270
lines changed

src/backend/catalog/heap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3219,7 +3219,7 @@ RemovePartitionKeyByRelId(Oid relid)
32193219
* the new partition's info into its partition descriptor.
32203220
*/
32213221
void
3222-
StorePartitionBound(Relation rel, Relation parent, Node *bound)
3222+
StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
32233223
{
32243224
Relation classRel;
32253225
HeapTuple tuple,

src/backend/catalog/partition.c

+34-30
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,16 @@ RelationBuildPartitionDesc(Relation rel)
247247
null_index = -1;
248248
foreach(cell, boundspecs)
249249
{
250+
PartitionBoundSpec *spec = castNode(PartitionBoundSpec,
251+
lfirst(cell));
250252
ListCell *c;
251-
PartitionBoundSpec *spec = lfirst(cell);
252253

253254
if (spec->strategy != PARTITION_STRATEGY_LIST)
254255
elog(ERROR, "invalid strategy in partition bound spec");
255256

256257
foreach(c, spec->listdatums)
257258
{
258-
Const *val = lfirst(c);
259+
Const *val = castNode(Const, lfirst(c));
259260
PartitionListValue *list_value = NULL;
260261

261262
if (!val->constisnull)
@@ -327,7 +328,8 @@ RelationBuildPartitionDesc(Relation rel)
327328
i = j = 0;
328329
foreach(cell, boundspecs)
329330
{
330-
PartitionBoundSpec *spec = lfirst(cell);
331+
PartitionBoundSpec *spec = castNode(PartitionBoundSpec,
332+
lfirst(cell));
331333
PartitionRangeBound *lower,
332334
*upper;
333335

@@ -665,9 +667,9 @@ partition_bounds_equal(PartitionKey key,
665667
* of parent. Also performs additional checks as necessary per strategy.
666668
*/
667669
void
668-
check_new_partition_bound(char *relname, Relation parent, Node *bound)
670+
check_new_partition_bound(char *relname, Relation parent,
671+
PartitionBoundSpec *spec)
669672
{
670-
PartitionBoundSpec *spec = (PartitionBoundSpec *) bound;
671673
PartitionKey key = RelationGetPartitionKey(parent);
672674
PartitionDesc partdesc = RelationGetPartitionDesc(parent);
673675
ParseState *pstate = make_parsestate(NULL);
@@ -692,7 +694,7 @@ check_new_partition_bound(char *relname, Relation parent, Node *bound)
692694

693695
foreach(cell, spec->listdatums)
694696
{
695-
Const *val = lfirst(cell);
697+
Const *val = castNode(Const, lfirst(cell));
696698

697699
if (!val->constisnull)
698700
{
@@ -889,9 +891,9 @@ get_partition_parent(Oid relid)
889891
* expressions as partition constraint
890892
*/
891893
List *
892-
get_qual_from_partbound(Relation rel, Relation parent, Node *bound)
894+
get_qual_from_partbound(Relation rel, Relation parent,
895+
PartitionBoundSpec *spec)
893896
{
894-
PartitionBoundSpec *spec = (PartitionBoundSpec *) bound;
895897
PartitionKey key = RelationGetPartitionKey(parent);
896898
List *my_qual = NIL;
897899

@@ -1328,7 +1330,7 @@ get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec)
13281330
prev = NULL;
13291331
for (cell = list_head(spec->listdatums); cell; cell = next)
13301332
{
1331-
Const *val = (Const *) lfirst(cell);
1333+
Const *val = castNode(Const, lfirst(cell));
13321334

13331335
next = lnext(cell);
13341336

@@ -1427,12 +1429,12 @@ get_range_key_properties(PartitionKey key, int keynum,
14271429
}
14281430

14291431
if (!ldatum->infinite)
1430-
*lower_val = (Const *) ldatum->value;
1432+
*lower_val = castNode(Const, ldatum->value);
14311433
else
14321434
*lower_val = NULL;
14331435

14341436
if (!udatum->infinite)
1435-
*upper_val = (Const *) udatum->value;
1437+
*upper_val = castNode(Const, udatum->value);
14361438
else
14371439
*upper_val = NULL;
14381440
}
@@ -1448,7 +1450,7 @@ get_range_key_properties(PartitionKey key, int keynum,
14481450
* as the lower bound tuple and (au, bu, cu) as the upper bound tuple, we
14491451
* generate an expression tree of the following form:
14501452
*
1451-
* (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
1453+
* (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
14521454
* AND
14531455
* (a > al OR (a = al AND b > bl) OR (a = al AND b = bl AND c >= cl))
14541456
* AND
@@ -1458,7 +1460,7 @@ get_range_key_properties(PartitionKey key, int keynum,
14581460
* the same values, for example, (al = au), in which case, we will emit an
14591461
* expression tree of the following form:
14601462
*
1461-
* (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
1463+
* (a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
14621464
* AND
14631465
* (a = al)
14641466
* AND
@@ -1512,8 +1514,8 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
15121514
num_or_arms = key->partnatts;
15131515

15141516
/*
1515-
* A range-partitioned table does not currently allow partition keys to
1516-
* be null, so emit an IS NOT NULL expression for each key column.
1517+
* A range-partitioned table does not currently allow partition keys to be
1518+
* null, so emit an IS NOT NULL expression for each key column.
15171519
*/
15181520
partexprs_item = list_head(key->partexprs);
15191521
for (i = 0; i < key->partnatts; i++)
@@ -1565,8 +1567,8 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
15651567
Datum test_result;
15661568
bool isNull;
15671569

1568-
ldatum = lfirst(cell1);
1569-
udatum = lfirst(cell2);
1570+
ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
1571+
udatum = castNode(PartitionRangeDatum, lfirst(cell2));
15701572

15711573
/*
15721574
* Since get_range_key_properties() modifies partexprs_item, and we
@@ -1644,12 +1646,14 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
16441646
PartitionRangeDatum *ldatum_next = NULL,
16451647
*udatum_next = NULL;
16461648

1647-
ldatum = lfirst(cell1);
1649+
ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
16481650
if (lnext(cell1))
1649-
ldatum_next = lfirst(lnext(cell1));
1650-
udatum = lfirst(cell2);
1651+
ldatum_next = castNode(PartitionRangeDatum,
1652+
lfirst(lnext(cell1)));
1653+
udatum = castNode(PartitionRangeDatum, lfirst(cell2));
16511654
if (lnext(cell2))
1652-
udatum_next = lfirst(lnext(cell2));
1655+
udatum_next = castNode(PartitionRangeDatum,
1656+
lfirst(lnext(cell2)));
16531657
get_range_key_properties(key, j, ldatum, udatum,
16541658
&partexprs_item,
16551659
&keyCol,
@@ -1779,7 +1783,7 @@ generate_partition_qual(Relation rel)
17791783
MemoryContext oldcxt;
17801784
Datum boundDatum;
17811785
bool isnull;
1782-
Node *bound;
1786+
PartitionBoundSpec *bound;
17831787
List *my_qual = NIL,
17841788
*result = NIL;
17851789
Relation parent;
@@ -1807,7 +1811,8 @@ generate_partition_qual(Relation rel)
18071811
if (isnull) /* should not happen */
18081812
elog(ERROR, "relation \"%s\" has relpartbound = null",
18091813
RelationGetRelationName(rel));
1810-
bound = stringToNode(TextDatumGetCString(boundDatum));
1814+
bound = castNode(PartitionBoundSpec,
1815+
stringToNode(TextDatumGetCString(boundDatum)));
18111816
ReleaseSysCache(tuple);
18121817

18131818
my_qual = get_qual_from_partbound(rel, parent, bound);
@@ -1971,9 +1976,8 @@ get_partition_for_tuple(PartitionDispatch *pd,
19711976
if (key->strategy == PARTITION_STRATEGY_RANGE)
19721977
{
19731978
/*
1974-
* Since we cannot route tuples with NULL partition keys through
1975-
* a range-partitioned table, simply return that no partition
1976-
* exists
1979+
* Since we cannot route tuples with NULL partition keys through a
1980+
* range-partitioned table, simply return that no partition exists
19771981
*/
19781982
for (i = 0; i < key->partnatts; i++)
19791983
{
@@ -2080,7 +2084,7 @@ static PartitionRangeBound *
20802084
make_one_range_bound(PartitionKey key, int index, List *datums, bool lower)
20812085
{
20822086
PartitionRangeBound *bound;
2083-
ListCell *cell;
2087+
ListCell *lc;
20842088
int i;
20852089

20862090
bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound));
@@ -2091,9 +2095,9 @@ make_one_range_bound(PartitionKey key, int index, List *datums, bool lower)
20912095
bound->lower = lower;
20922096

20932097
i = 0;
2094-
foreach(cell, datums)
2098+
foreach(lc, datums)
20952099
{
2096-
PartitionRangeDatum *datum = lfirst(cell);
2100+
PartitionRangeDatum *datum = castNode(PartitionRangeDatum, lfirst(lc));
20972101

20982102
/* What's contained in this range datum? */
20992103
bound->content[i] = !datum->infinite
@@ -2103,7 +2107,7 @@ make_one_range_bound(PartitionKey key, int index, List *datums, bool lower)
21032107

21042108
if (bound->content[i] == RANGE_DATUM_FINITE)
21052109
{
2106-
Const *val = (Const *) datum->value;
2110+
Const *val = castNode(Const, datum->value);
21072111

21082112
if (val->constisnull)
21092113
elog(ERROR, "invalid range bound datum");

0 commit comments

Comments
 (0)