Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbb4114a

Browse files
committed
Allow whole-row Vars to be used in partitioning expressions.
In the wake of commit5b93123, there's no particular reasonfor this restriction (previously, it was problematic because ofthe implied rowtype reference). A simple constraint on a whole-rowVar probably isn't that useful, but conceivably somebody would wantto pass one to a function that extracts a partitioning key. Besideswhich, we're expending much more code to enforce the restriction thanwe save by having it, since the latter quantity is now zero.So drop the restriction.Amit LangoteDiscussion:https://postgr.es/m/CA+HiwqFUzjfj9HEsJtYWcr1SgQ_=iCAvQ=O2Sx6aQxoDu4OiHw@mail.gmail.com
1 parent42f74f4 commitbb4114a

File tree

8 files changed

+64
-77
lines changed

8 files changed

+64
-77
lines changed

‎src/backend/catalog/partition.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -181,45 +181,38 @@ index_get_partition(Relation partition, Oid indexId)
181181
}
182182

183183
/*
184-
* map_partition_varattnos - mapsvarattno ofany Vars in expr from the
185-
*attno's of 'from_rel' to theattno's of 'to_rel' partition, each of which
186-
* may be either a leaf partition or a partitioned table, but both of which
187-
* must be from the same partitioning hierarchy.
184+
* map_partition_varattnos - mapsvarattnos ofall Vars in'expr' (that have
185+
*varno 'fromrel_varno') from theattnums of 'from_rel' to the attnums of
186+
*'to_rel', each of whichmay be either a leaf partition or a partitioned
187+
*table, but both of whichmust be from the same partitioning hierarchy.
188188
*
189-
* Even though all of the same column names must be present in all relations
190-
* in the hierarchy, and they must also have the same types, the attnos may
191-
* be different.
192-
*
193-
* If found_whole_row is not NULL, *found_whole_row returns whether a
194-
* whole-row variable was found in the input expression.
189+
* We need this because even though all of the same column names must be
190+
* present in all relations in the hierarchy, and they must also have the
191+
* same types, the attnums may be different.
195192
*
196193
* Note: this will work on any node tree, so really the argument and result
197194
* should be declared "Node *". But a substantial majority of the callers
198195
* are working on Lists, so it's less messy to do the casts internally.
199196
*/
200197
List*
201198
map_partition_varattnos(List*expr,intfromrel_varno,
202-
Relationto_rel,Relationfrom_rel,
203-
bool*found_whole_row)
199+
Relationto_rel,Relationfrom_rel)
204200
{
205-
boolmy_found_whole_row= false;
206-
207201
if (expr!=NIL)
208202
{
209203
AttrMap*part_attmap;
204+
boolfound_whole_row;
210205

211206
part_attmap=build_attrmap_by_name(RelationGetDescr(to_rel),
212207
RelationGetDescr(from_rel));
213208
expr= (List*)map_variable_attnos((Node*)expr,
214209
fromrel_varno,0,
215210
part_attmap,
216211
RelationGetForm(to_rel)->reltype,
217-
&my_found_whole_row);
212+
&found_whole_row);
213+
/* Since we provided a to_rowtype, we may ignore found_whole_row. */
218214
}
219215

220-
if (found_whole_row)
221-
*found_whole_row=my_found_whole_row;
222-
223216
returnexpr;
224217
}
225218

‎src/backend/commands/tablecmds.c

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15168,15 +15168,11 @@ ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNu
1516815168
*/
1516915169

1517015170
/*
15171-
* Cannot have expressions containing whole-row references or
15172-
* system column references.
15171+
* Cannot allow system column references, since that would
15172+
* make partition routing impossible: their values won't be
15173+
* known yet when we need to do that.
1517315174
*/
1517415175
pull_varattnos(expr, 1, &expr_attrs);
15175-
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
15176-
expr_attrs))
15177-
ereport(ERROR,
15178-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
15179-
errmsg("partition key expressions cannot contain whole-row references")));
1518015176
for (i = FirstLowInvalidHeapAttributeNumber; i < 0; i++)
1518115177
{
1518215178
if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
@@ -15196,7 +15192,8 @@ ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNu
1519615192
{
1519715193
AttrNumberattno = i + FirstLowInvalidHeapAttributeNumber;
1519815194

15199-
if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
15195+
if (attno > 0 &&
15196+
TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
1520015197
ereport(ERROR,
1520115198
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1520215199
errmsg("cannot use generated column in partition key"),
@@ -15451,7 +15448,6 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel,
1545115448
for (i = 0; i < partdesc->nparts; i++)
1545215449
{
1545315450
Relationpart_rel;
15454-
boolfound_whole_row;
1545515451
List *thisPartConstraint;
1545615452

1545715453
/*
@@ -15465,10 +15461,7 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel,
1546515461
*/
1546615462
thisPartConstraint =
1546715463
map_partition_varattnos(partConstraint, 1,
15468-
part_rel, scanrel, &found_whole_row);
15469-
/* There can never be a whole-row reference here */
15470-
if (found_whole_row)
15471-
elog(ERROR, "unexpected whole-row reference found in partition constraint");
15464+
part_rel, scanrel);
1547215465

1547315466
QueuePartitionConstraintValidation(wqueue, part_rel,
1547415467
thisPartConstraint,
@@ -15497,7 +15490,6 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1549715490
TupleDesctupleDesc;
1549815491
ObjectAddress address;
1549915492
const char *trigger_name;
15500-
boolfound_whole_row;
1550115493
OiddefaultPartOid;
1550215494
List *partBoundConstraint;
1550315495

@@ -15714,11 +15706,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1571415706
* numbers.
1571515707
*/
1571615708
partConstraint = map_partition_varattnos(partConstraint, 1, attachrel,
15717-
rel, &found_whole_row);
15718-
/* There can never be a whole-row reference here */
15719-
if (found_whole_row)
15720-
elog(ERROR,
15721-
"unexpected whole-row reference found in partition key");
15709+
rel);
1572215710

1572315711
/* Validate partition constraints against the table being attached. */
1572415712
QueuePartitionConstraintValidation(wqueue, attachrel, partConstraint,
@@ -15750,7 +15738,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1575015738
*/
1575115739
defPartConstraint =
1575215740
map_partition_varattnos(defPartConstraint,
15753-
1, defaultrel, rel, NULL);
15741+
1, defaultrel, rel);
1575415742
QueuePartitionConstraintValidation(wqueue, defaultrel,
1575515743
defPartConstraint, true);
1575615744

@@ -16004,19 +15992,11 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1600415992
RelationGetDescr(pg_trigger), &isnull);
1600515993
if (!isnull)
1600615994
{
16007-
boolfound_whole_row;
16008-
1600915995
qual = stringToNode(TextDatumGetCString(value));
1601015996
qual = (Node *) map_partition_varattnos((List *) qual, PRS2_OLD_VARNO,
16011-
partition, parent,
16012-
&found_whole_row);
16013-
if (found_whole_row)
16014-
elog(ERROR, "unexpected whole-row reference found in trigger WHEN clause");
15997+
partition, parent);
1601515998
qual = (Node *) map_partition_varattnos((List *) qual, PRS2_NEW_VARNO,
16016-
partition, parent,
16017-
&found_whole_row);
16018-
if (found_whole_row)
16019-
elog(ERROR, "unexpected whole-row reference found in trigger WHEN clause");
15999+
partition, parent);
1602016000
}
1602116001

1602216002
/*

‎src/backend/commands/trigger.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
11441144
CreateTrigStmt*childStmt;
11451145
RelationchildTbl;
11461146
Node*qual;
1147-
boolfound_whole_row;
11481147

11491148
childTbl=table_open(partdesc->oids[i],ShareRowExclusiveLock);
11501149

@@ -1177,16 +1176,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
11771176
qual=copyObject(whenClause);
11781177
qual= (Node*)
11791178
map_partition_varattnos((List*)qual,PRS2_OLD_VARNO,
1180-
childTbl,rel,
1181-
&found_whole_row);
1182-
if (found_whole_row)
1183-
elog(ERROR,"unexpected whole-row reference found in trigger WHEN clause");
1179+
childTbl,rel);
11841180
qual= (Node*)
11851181
map_partition_varattnos((List*)qual,PRS2_NEW_VARNO,
1186-
childTbl,rel,
1187-
&found_whole_row);
1188-
if (found_whole_row)
1189-
elog(ERROR,"unexpected whole-row reference found in trigger WHEN clause");
1182+
childTbl,rel);
11901183

11911184
CreateTrigger(childStmt,queryString,
11921185
partdesc->oids[i],refRelOid,

‎src/backend/partitioning/partbounds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ check_default_partition_contents(Relation parent, Relation default_rel,
12471247
*/
12481248
def_part_constraints=
12491249
map_partition_varattnos(def_part_constraints,1,default_rel,
1250-
parent,NULL);
1250+
parent);
12511251

12521252
/*
12531253
* If the existing constraints on the default partition imply that it will
@@ -1297,7 +1297,7 @@ check_default_partition_contents(Relation parent, Relation default_rel,
12971297
partition_constraint=make_ands_explicit(def_part_constraints);
12981298
partition_constraint= (Expr*)
12991299
map_partition_varattnos((List*)partition_constraint,1,
1300-
part_rel,default_rel,NULL);
1300+
part_rel,default_rel);
13011301

13021302
/*
13031303
* If the partition constraints on default partition child imply

‎src/backend/utils/cache/partcache.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ generate_partition_qual(Relation rel)
342342
List*my_qual=NIL,
343343
*result=NIL;
344344
Relationparent;
345-
boolfound_whole_row;
346345

347346
/* Guard against stack overflow due to overly deep partition tree */
348347
check_stack_depth();
@@ -388,11 +387,7 @@ generate_partition_qual(Relation rel)
388387
* in it to bear this relation's attnos. It's safe to assume varno = 1
389388
* here.
390389
*/
391-
result=map_partition_varattnos(result,1,rel,parent,
392-
&found_whole_row);
393-
/* There can never be a whole-row reference here */
394-
if (found_whole_row)
395-
elog(ERROR,"unexpected whole-row reference found in partition key");
390+
result=map_partition_varattnos(result,1,rel,parent);
396391

397392
/* Assert that we're not leaking any old data during assignments below */
398393
Assert(rel->rd_partcheckcxt==NULL);

‎src/include/catalog/partition.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ extern Oidget_partition_parent(Oid relid);
2323
externList*get_partition_ancestors(Oidrelid);
2424
externOidindex_get_partition(Relationpartition,OidindexId);
2525
externList*map_partition_varattnos(List*expr,intfromrel_varno,
26-
Relationto_rel,Relationfrom_rel,
27-
bool*found_whole_row);
26+
Relationto_rel,Relationfrom_rel);
2827
externboolhas_partition_attrs(Relationrel,Bitmapset*attnums,
2928
bool*used_in_expr);
3029

‎src/test/regress/expected/create_table.out

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,6 @@ CREATE TABLE partitioned (
420420
) PARTITION BY RANGE (immut_func(a));
421421
ERROR: functions in partition key expression must be marked IMMUTABLE
422422
DROP FUNCTION immut_func(int);
423-
-- cannot contain whole-row references
424-
CREATE TABLE partitioned (
425-
aint
426-
) PARTITION BY RANGE ((partitioned));
427-
ERROR: partition key expressions cannot contain whole-row references
428423
-- prevent using columns of unsupported types in key (type must have a btree operator class)
429424
CREATE TABLE partitioned (
430425
a point
@@ -527,6 +522,31 @@ select * from partitioned where row(a,b)::partitioned = '(1,2)'::partitioned;
527522
Filter: (ROW(a, b)::partitioned = '(1,2)'::partitioned)
528523
(2 rows)
529524

525+
drop table partitioned;
526+
-- whole-row Var in partition key works too
527+
create table partitioned (a int, b int)
528+
partition by list ((partitioned));
529+
create table partitioned1
530+
partition of partitioned for values in ('(1,2)');
531+
create table partitioned2
532+
partition of partitioned for values in ('(2,4)');
533+
explain (costs off)
534+
select * from partitioned where partitioned = '(1,2)'::partitioned;
535+
QUERY PLAN
536+
-----------------------------------------------------------------
537+
Seq Scan on partitioned1 partitioned
538+
Filter: ((partitioned.*)::partitioned = '(1,2)'::partitioned)
539+
(2 rows)
540+
541+
\d+ partitioned1
542+
Table "public.partitioned1"
543+
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
544+
--------+---------+-----------+----------+---------+---------+--------------+-------------
545+
a | integer | | | | plain | |
546+
b | integer | | | | plain | |
547+
Partition of: partitioned FOR VALUES IN ('(1,2)')
548+
Partition constraint: (((partitioned1.*)::partitioned IS DISTINCT FROM NULL) AND ((partitioned1.*)::partitioned = '(1,2)'::partitioned))
549+
530550
drop table partitioned;
531551
-- check that dependencies of partition columns are handled correctly
532552
create domain intdom1 as int;

‎src/test/regress/sql/create_table.sql

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,6 @@ CREATE TABLE partitioned (
401401
) PARTITION BY RANGE (immut_func(a));
402402
DROPFUNCTION immut_func(int);
403403

404-
-- cannot contain whole-row references
405-
CREATETABLEpartitioned (
406-
aint
407-
) PARTITION BY RANGE ((partitioned));
408-
409404
-- prevent using columns of unsupported types in key (type must have a btree operator class)
410405
CREATETABLEpartitioned (
411406
apoint
@@ -470,6 +465,18 @@ explain (costs off)
470465
select*from partitionedwhere row(a,b)::partitioned='(1,2)'::partitioned;
471466
droptable partitioned;
472467

468+
-- whole-row Var in partition key works too
469+
createtablepartitioned (aint, bint)
470+
partition by list ((partitioned));
471+
createtablepartitioned1
472+
partition of partitioned forvaluesin ('(1,2)');
473+
createtablepartitioned2
474+
partition of partitioned forvaluesin ('(2,4)');
475+
explain (costs off)
476+
select*from partitionedwhere partitioned='(1,2)'::partitioned;
477+
\d+ partitioned1
478+
droptable partitioned;
479+
473480
-- check that dependencies of partition columns are handled correctly
474481
createdomainintdom1asint;
475482

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp