@@ -852,10 +852,6 @@ get_qual_from_partbound(Relation rel, Relation parent, Node *bound)
852
852
PartitionBoundSpec * spec = (PartitionBoundSpec * ) bound ;
853
853
PartitionKey key = RelationGetPartitionKey (parent );
854
854
List * my_qual = NIL ;
855
- TupleDesc parent_tupdesc = RelationGetDescr (parent );
856
- AttrNumber parent_attno ;
857
- AttrNumber * partition_attnos ;
858
- bool found_whole_row ;
859
855
860
856
Assert (key != NULL );
861
857
@@ -876,38 +872,51 @@ get_qual_from_partbound(Relation rel, Relation parent, Node *bound)
876
872
(int ) key -> strategy );
877
873
}
878
874
879
- /*
880
- * Translate vars in the generated expression to have correct attnos. Note
881
- * that the vars in my_qual bear attnos dictated by key which carries
882
- * physical attnos of the parent. We must allow for a case where physical
883
- * attnos of a partition can be different from the parent.
884
- */
885
- partition_attnos = (AttrNumber * )
886
- palloc0 (parent_tupdesc -> natts * sizeof (AttrNumber ));
887
- for (parent_attno = 1 ; parent_attno <= parent_tupdesc -> natts ;
888
- parent_attno ++ )
875
+ return my_qual ;
876
+ }
877
+
878
+ /*
879
+ * map_partition_varattnos - maps varattno of any Vars in expr from the
880
+ * parent attno to partition attno.
881
+ *
882
+ * We must allow for a case where physical attnos of a partition can be
883
+ * different from the parent's.
884
+ */
885
+ List *
886
+ map_partition_varattnos (List * expr , Relation partrel , Relation parent )
887
+ {
888
+ TupleDesc tupdesc = RelationGetDescr (parent );
889
+ AttrNumber attno ;
890
+ AttrNumber * part_attnos ;
891
+ bool found_whole_row ;
892
+
893
+ if (expr == NIL )
894
+ return NIL ;
895
+
896
+ part_attnos = (AttrNumber * ) palloc0 (tupdesc -> natts * sizeof (AttrNumber ));
897
+ for (attno = 1 ; attno <= tupdesc -> natts ; attno ++ )
889
898
{
890
- Form_pg_attribute attribute = parent_tupdesc -> attrs [parent_attno - 1 ];
899
+ Form_pg_attribute attribute = tupdesc -> attrs [attno - 1 ];
891
900
char * attname = NameStr (attribute -> attname );
892
- AttrNumber partition_attno ;
901
+ AttrNumber part_attno ;
893
902
894
903
if (attribute -> attisdropped )
895
904
continue ;
896
905
897
- partition_attno = get_attnum (RelationGetRelid (rel ), attname );
898
- partition_attnos [ parent_attno - 1 ] = partition_attno ;
906
+ part_attno = get_attnum (RelationGetRelid (partrel ), attname );
907
+ part_attnos [ attno - 1 ] = part_attno ;
899
908
}
900
909
901
- my_qual = (List * ) map_variable_attnos ((Node * ) my_qual ,
902
- 1 , 0 ,
903
- partition_attnos ,
904
- parent_tupdesc -> natts ,
905
- & found_whole_row );
906
- /* there can never be a whole-row reference here */
910
+ expr = (List * ) map_variable_attnos ((Node * ) expr ,
911
+ 1 , 0 ,
912
+ part_attnos ,
913
+ tupdesc -> natts ,
914
+ & found_whole_row );
915
+ /* There can never be a whole-row reference here */
907
916
if (found_whole_row )
908
917
elog (ERROR , "unexpected whole-row reference found in partition key" );
909
918
910
- return my_qual ;
919
+ return expr ;
911
920
}
912
921
913
922
/*
@@ -1496,27 +1505,15 @@ generate_partition_qual(Relation rel)
1496
1505
/* Guard against stack overflow due to overly deep partition tree */
1497
1506
check_stack_depth ();
1498
1507
1508
+ /* Quick copy */
1509
+ if (rel -> rd_partcheck != NIL )
1510
+ return copyObject (rel -> rd_partcheck );
1511
+
1499
1512
/* Grab at least an AccessShareLock on the parent table */
1500
1513
parent = heap_open (get_partition_parent (RelationGetRelid (rel )),
1501
1514
AccessShareLock );
1502
1515
1503
- /* Quick copy */
1504
- if (rel -> rd_partcheck )
1505
- {
1506
- if (parent -> rd_rel -> relispartition )
1507
- result = list_concat (generate_partition_qual (parent ),
1508
- copyObject (rel -> rd_partcheck ));
1509
- else
1510
- result = copyObject (rel -> rd_partcheck );
1511
-
1512
- heap_close (parent , AccessShareLock );
1513
- return result ;
1514
- }
1515
-
1516
1516
/* Get pg_class.relpartbound */
1517
- if (!rel -> rd_rel -> relispartition ) /* should not happen */
1518
- elog (ERROR , "relation \"%s\" has relispartition = false" ,
1519
- RelationGetRelationName (rel ));
1520
1517
tuple = SearchSysCache1 (RELOID , RelationGetRelid (rel ));
1521
1518
if (!HeapTupleIsValid (tuple ))
1522
1519
elog (ERROR , "cache lookup failed for relation %u" ,
@@ -1533,20 +1530,22 @@ generate_partition_qual(Relation rel)
1533
1530
1534
1531
my_qual = get_qual_from_partbound (rel , parent , bound );
1535
1532
1536
- /* If requested, add parent's quals to the list (if any) */
1533
+ /* Add the parent's quals to the list (if any) */
1537
1534
if (parent -> rd_rel -> relispartition )
1538
- {
1539
- List * parent_check ;
1540
-
1541
- parent_check = generate_partition_qual (parent );
1542
- result = list_concat (parent_check , my_qual );
1543
- }
1535
+ result = list_concat (generate_partition_qual (parent ), my_qual );
1544
1536
else
1545
1537
result = my_qual ;
1546
1538
1547
- /* Save a copy of my_qual in the relcache */
1539
+ /*
1540
+ * Change Vars to have partition's attnos instead of the parent's.
1541
+ * We do this after we concatenate the parent's quals, because
1542
+ * we want every Var in it to bear this relation's attnos.
1543
+ */
1544
+ result = map_partition_varattnos (result , rel , parent );
1545
+
1546
+ /* Save a copy in the relcache */
1548
1547
oldcxt = MemoryContextSwitchTo (CacheMemoryContext );
1549
- rel -> rd_partcheck = copyObject (my_qual );
1548
+ rel -> rd_partcheck = copyObject (result );
1550
1549
MemoryContextSwitchTo (oldcxt );
1551
1550
1552
1551
/* Keep the parent locked until commit */
0 commit comments