55
55
typedef struct
56
56
{
57
57
PlannerInfo * root ;
58
- AppendRelInfo * appinfo ;
58
+ int nappinfos ;
59
+ AppendRelInfo * * appinfos ;
59
60
} adjust_appendrel_attrs_context ;
60
61
61
62
static Path * recurse_set_operations (Node * setOp , PlannerInfo * root ,
@@ -107,7 +108,8 @@ static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
107
108
List * translated_vars );
108
109
static Node * adjust_appendrel_attrs_mutator (Node * node ,
109
110
adjust_appendrel_attrs_context * context );
110
- static Relids adjust_relid_set (Relids relids , Index oldrelid , Index newrelid );
111
+ static Relids adjust_child_relids (Relids relids , int nappinfos ,
112
+ AppendRelInfo * * appinfos );
111
113
static List * adjust_inherited_tlist (List * tlist ,
112
114
AppendRelInfo * context );
113
115
@@ -1775,10 +1777,10 @@ translate_col_privs(const Bitmapset *parent_privs,
1775
1777
1776
1778
/*
1777
1779
* adjust_appendrel_attrs
1778
- * Copy the specified query or expression and translate Vars referring
1779
- * to the parent rel of the specified AppendRelInfo to refer to the
1780
- * child rel instead. We also update rtindexes appearing outside Vars,
1781
- * such as resultRelation and jointree relids.
1780
+ * Copy the specified query or expression and translate Vars referring to a
1781
+ * parent rel to refer to the corresponding child rel instead. We also
1782
+ * update rtindexes appearing outside Vars, such as resultRelation and
1783
+ * jointree relids.
1782
1784
*
1783
1785
* Note: this is only applied after conversion of sublinks to subplans,
1784
1786
* so we don't need to cope with recursion into sub-queries.
@@ -1787,34 +1789,47 @@ translate_col_privs(const Bitmapset *parent_privs,
1787
1789
* maybe we should try to fold the two routines together.
1788
1790
*/
1789
1791
Node *
1790
- adjust_appendrel_attrs (PlannerInfo * root , Node * node , AppendRelInfo * appinfo )
1792
+ adjust_appendrel_attrs (PlannerInfo * root , Node * node , int nappinfos ,
1793
+ AppendRelInfo * * appinfos )
1791
1794
{
1792
1795
Node * result ;
1793
1796
adjust_appendrel_attrs_context context ;
1794
1797
1795
1798
context .root = root ;
1796
- context .appinfo = appinfo ;
1799
+ context .nappinfos = nappinfos ;
1800
+ context .appinfos = appinfos ;
1801
+
1802
+ /* If there's nothing to adjust, don't call this function. */
1803
+ Assert (nappinfos >= 1 && appinfos != NULL );
1797
1804
1798
1805
/*
1799
1806
* Must be prepared to start with a Query or a bare expression tree.
1800
1807
*/
1801
1808
if (node && IsA (node , Query ))
1802
1809
{
1803
1810
Query * newnode ;
1811
+ int cnt ;
1804
1812
1805
1813
newnode = query_tree_mutator ((Query * ) node ,
1806
1814
adjust_appendrel_attrs_mutator ,
1807
1815
(void * ) & context ,
1808
1816
QTW_IGNORE_RC_SUBQUERIES );
1809
- if ( newnode -> resultRelation == appinfo -> parent_relid )
1817
+ for ( cnt = 0 ; cnt < nappinfos ; cnt ++ )
1810
1818
{
1811
- newnode -> resultRelation = appinfo -> child_relid ;
1812
- /* Fix tlist resnos too, if it's inherited UPDATE */
1813
- if (newnode -> commandType == CMD_UPDATE )
1814
- newnode -> targetList =
1815
- adjust_inherited_tlist (newnode -> targetList ,
1816
- appinfo );
1819
+ AppendRelInfo * appinfo = appinfos [cnt ];
1820
+
1821
+ if (newnode -> resultRelation == appinfo -> parent_relid )
1822
+ {
1823
+ newnode -> resultRelation = appinfo -> child_relid ;
1824
+ /* Fix tlist resnos too, if it's inherited UPDATE */
1825
+ if (newnode -> commandType == CMD_UPDATE )
1826
+ newnode -> targetList =
1827
+ adjust_inherited_tlist (newnode -> targetList ,
1828
+ appinfo );
1829
+ break ;
1830
+ }
1817
1831
}
1832
+
1818
1833
result = (Node * ) newnode ;
1819
1834
}
1820
1835
else
@@ -1827,16 +1842,27 @@ static Node *
1827
1842
adjust_appendrel_attrs_mutator (Node * node ,
1828
1843
adjust_appendrel_attrs_context * context )
1829
1844
{
1830
- AppendRelInfo * appinfo = context -> appinfo ;
1845
+ AppendRelInfo * * appinfos = context -> appinfos ;
1846
+ int nappinfos = context -> nappinfos ;
1847
+ int cnt ;
1831
1848
1832
1849
if (node == NULL )
1833
1850
return NULL ;
1834
1851
if (IsA (node , Var ))
1835
1852
{
1836
1853
Var * var = (Var * ) copyObject (node );
1854
+ AppendRelInfo * appinfo = NULL ;
1837
1855
1838
- if (var -> varlevelsup == 0 &&
1839
- var -> varno == appinfo -> parent_relid )
1856
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
1857
+ {
1858
+ if (var -> varno == appinfos [cnt ]-> parent_relid )
1859
+ {
1860
+ appinfo = appinfos [cnt ];
1861
+ break ;
1862
+ }
1863
+ }
1864
+
1865
+ if (var -> varlevelsup == 0 && appinfo )
1840
1866
{
1841
1867
var -> varno = appinfo -> child_relid ;
1842
1868
var -> varnoold = appinfo -> child_relid ;
@@ -1916,29 +1942,54 @@ adjust_appendrel_attrs_mutator(Node *node,
1916
1942
{
1917
1943
CurrentOfExpr * cexpr = (CurrentOfExpr * ) copyObject (node );
1918
1944
1919
- if (cexpr -> cvarno == appinfo -> parent_relid )
1920
- cexpr -> cvarno = appinfo -> child_relid ;
1945
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
1946
+ {
1947
+ AppendRelInfo * appinfo = appinfos [cnt ];
1948
+
1949
+ if (cexpr -> cvarno == appinfo -> parent_relid )
1950
+ {
1951
+ cexpr -> cvarno = appinfo -> child_relid ;
1952
+ break ;
1953
+ }
1954
+ }
1921
1955
return (Node * ) cexpr ;
1922
1956
}
1923
1957
if (IsA (node , RangeTblRef ))
1924
1958
{
1925
1959
RangeTblRef * rtr = (RangeTblRef * ) copyObject (node );
1926
1960
1927
- if (rtr -> rtindex == appinfo -> parent_relid )
1928
- rtr -> rtindex = appinfo -> child_relid ;
1961
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
1962
+ {
1963
+ AppendRelInfo * appinfo = appinfos [cnt ];
1964
+
1965
+ if (rtr -> rtindex == appinfo -> parent_relid )
1966
+ {
1967
+ rtr -> rtindex = appinfo -> child_relid ;
1968
+ break ;
1969
+ }
1970
+ }
1929
1971
return (Node * ) rtr ;
1930
1972
}
1931
1973
if (IsA (node , JoinExpr ))
1932
1974
{
1933
1975
/* Copy the JoinExpr node with correct mutation of subnodes */
1934
1976
JoinExpr * j ;
1977
+ AppendRelInfo * appinfo ;
1935
1978
1936
1979
j = (JoinExpr * ) expression_tree_mutator (node ,
1937
1980
adjust_appendrel_attrs_mutator ,
1938
1981
(void * ) context );
1939
1982
/* now fix JoinExpr's rtindex (probably never happens) */
1940
- if (j -> rtindex == appinfo -> parent_relid )
1941
- j -> rtindex = appinfo -> child_relid ;
1983
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
1984
+ {
1985
+ appinfo = appinfos [cnt ];
1986
+
1987
+ if (j -> rtindex == appinfo -> parent_relid )
1988
+ {
1989
+ j -> rtindex = appinfo -> child_relid ;
1990
+ break ;
1991
+ }
1992
+ }
1942
1993
return (Node * ) j ;
1943
1994
}
1944
1995
if (IsA (node , PlaceHolderVar ))
@@ -1951,9 +2002,8 @@ adjust_appendrel_attrs_mutator(Node *node,
1951
2002
(void * ) context );
1952
2003
/* now fix PlaceHolderVar's relid sets */
1953
2004
if (phv -> phlevelsup == 0 )
1954
- phv -> phrels = adjust_relid_set (phv -> phrels ,
1955
- appinfo -> parent_relid ,
1956
- appinfo -> child_relid );
2005
+ phv -> phrels = adjust_child_relids (phv -> phrels , context -> nappinfos ,
2006
+ context -> appinfos );
1957
2007
return (Node * ) phv ;
1958
2008
}
1959
2009
/* Shouldn't need to handle planner auxiliary nodes here */
@@ -1984,24 +2034,24 @@ adjust_appendrel_attrs_mutator(Node *node,
1984
2034
adjust_appendrel_attrs_mutator ((Node * ) oldinfo -> orclause , context );
1985
2035
1986
2036
/* adjust relid sets too */
1987
- newinfo -> clause_relids = adjust_relid_set (oldinfo -> clause_relids ,
1988
- appinfo -> parent_relid ,
1989
- appinfo -> child_relid );
1990
- newinfo -> required_relids = adjust_relid_set (oldinfo -> required_relids ,
1991
- appinfo -> parent_relid ,
1992
- appinfo -> child_relid );
1993
- newinfo -> outer_relids = adjust_relid_set (oldinfo -> outer_relids ,
1994
- appinfo -> parent_relid ,
1995
- appinfo -> child_relid );
1996
- newinfo -> nullable_relids = adjust_relid_set (oldinfo -> nullable_relids ,
1997
- appinfo -> parent_relid ,
1998
- appinfo -> child_relid );
1999
- newinfo -> left_relids = adjust_relid_set (oldinfo -> left_relids ,
2000
- appinfo -> parent_relid ,
2001
- appinfo -> child_relid );
2002
- newinfo -> right_relids = adjust_relid_set (oldinfo -> right_relids ,
2003
- appinfo -> parent_relid ,
2004
- appinfo -> child_relid );
2037
+ newinfo -> clause_relids = adjust_child_relids (oldinfo -> clause_relids ,
2038
+ context -> nappinfos ,
2039
+ context -> appinfos );
2040
+ newinfo -> required_relids = adjust_child_relids (oldinfo -> required_relids ,
2041
+ context -> nappinfos ,
2042
+ context -> appinfos );
2043
+ newinfo -> outer_relids = adjust_child_relids (oldinfo -> outer_relids ,
2044
+ context -> nappinfos ,
2045
+ context -> appinfos );
2046
+ newinfo -> nullable_relids = adjust_child_relids (oldinfo -> nullable_relids ,
2047
+ context -> nappinfos ,
2048
+ context -> appinfos );
2049
+ newinfo -> left_relids = adjust_child_relids (oldinfo -> left_relids ,
2050
+ context -> nappinfos ,
2051
+ context -> appinfos );
2052
+ newinfo -> right_relids = adjust_child_relids (oldinfo -> right_relids ,
2053
+ context -> nappinfos ,
2054
+ context -> appinfos );
2005
2055
2006
2056
/*
2007
2057
* Reset cached derivative fields, since these might need to have
@@ -2033,19 +2083,36 @@ adjust_appendrel_attrs_mutator(Node *node,
2033
2083
}
2034
2084
2035
2085
/*
2036
- * Substitute newrelid for oldrelid in a Relid set
2086
+ * Substitute child relids for parent relids in a Relid set. The array of
2087
+ * appinfos specifies the substitutions to be performed.
2037
2088
*/
2038
- static Relids
2039
- adjust_relid_set (Relids relids , Index oldrelid , Index newrelid )
2089
+ Relids
2090
+ adjust_child_relids (Relids relids , int nappinfos , AppendRelInfo * * appinfos )
2040
2091
{
2041
- if (bms_is_member (oldrelid , relids ))
2092
+ Bitmapset * result = NULL ;
2093
+ int cnt ;
2094
+
2095
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
2042
2096
{
2043
- /* Ensure we have a modifiable copy */
2044
- relids = bms_copy (relids );
2045
- /* Remove old, add new */
2046
- relids = bms_del_member (relids , oldrelid );
2047
- relids = bms_add_member (relids , newrelid );
2097
+ AppendRelInfo * appinfo = appinfos [cnt ];
2098
+
2099
+ /* Remove parent, add child */
2100
+ if (bms_is_member (appinfo -> parent_relid , relids ))
2101
+ {
2102
+ /* Make a copy if we are changing the set. */
2103
+ if (!result )
2104
+ result = bms_copy (relids );
2105
+
2106
+ result = bms_del_member (result , appinfo -> parent_relid );
2107
+ result = bms_add_member (result , appinfo -> child_relid );
2108
+ }
2048
2109
}
2110
+
2111
+ /* If we made any changes, return the modified copy. */
2112
+ if (result )
2113
+ return result ;
2114
+
2115
+ /* Otherwise, return the original set without modification. */
2049
2116
return relids ;
2050
2117
}
2051
2118
@@ -2150,21 +2217,77 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
2150
2217
* adjust_appendrel_attrs_multilevel
2151
2218
* Apply Var translations from a toplevel appendrel parent down to a child.
2152
2219
*
2153
- * In some cases we need to translate expressions referencing a baserel
2220
+ * In some cases we need to translate expressions referencing a parent relation
2154
2221
* to reference an appendrel child that's multiple levels removed from it.
2155
2222
*/
2156
2223
Node *
2157
2224
adjust_appendrel_attrs_multilevel (PlannerInfo * root , Node * node ,
2158
- RelOptInfo * child_rel )
2225
+ Relids child_relids ,
2226
+ Relids top_parent_relids )
2159
2227
{
2160
- AppendRelInfo * appinfo = find_childrel_appendrelinfo (root , child_rel );
2161
- RelOptInfo * parent_rel = find_base_rel (root , appinfo -> parent_relid );
2228
+ AppendRelInfo * * appinfos ;
2229
+ Bitmapset * parent_relids = NULL ;
2230
+ int nappinfos ;
2231
+ int cnt ;
2232
+
2233
+ Assert (bms_num_members (child_relids ) == bms_num_members (top_parent_relids ));
2234
+
2235
+ appinfos = find_appinfos_by_relids (root , child_relids , & nappinfos );
2236
+
2237
+ /* Construct relids set for the immediate parent of given child. */
2238
+ for (cnt = 0 ; cnt < nappinfos ; cnt ++ )
2239
+ {
2240
+ AppendRelInfo * appinfo = appinfos [cnt ];
2241
+
2242
+ parent_relids = bms_add_member (parent_relids , appinfo -> parent_relid );
2243
+ }
2244
+
2245
+ /* Recurse if immediate parent is not the top parent. */
2246
+ if (!bms_equal (parent_relids , top_parent_relids ))
2247
+ node = adjust_appendrel_attrs_multilevel (root , node , parent_relids ,
2248
+ top_parent_relids );
2162
2249
2163
- /* If parent is also a child, first recurse to apply its translations */
2164
- if (IS_OTHER_REL (parent_rel ))
2165
- node = adjust_appendrel_attrs_multilevel (root , node , parent_rel );
2166
- else
2167
- Assert (parent_rel -> reloptkind == RELOPT_BASEREL );
2168
2250
/* Now translate for this child */
2169
- return adjust_appendrel_attrs (root , node , appinfo );
2251
+ node = adjust_appendrel_attrs (root , node , nappinfos , appinfos );
2252
+
2253
+ pfree (appinfos );
2254
+
2255
+ return node ;
2256
+ }
2257
+
2258
+ /*
2259
+ * find_appinfos_by_relids
2260
+ * Find AppendRelInfo structures for all relations specified by relids.
2261
+ *
2262
+ * The AppendRelInfos are returned in an array, which can be pfree'd by the
2263
+ * caller. *nappinfos is set to the the number of entries in the array.
2264
+ */
2265
+ AppendRelInfo * *
2266
+ find_appinfos_by_relids (PlannerInfo * root , Relids relids , int * nappinfos )
2267
+ {
2268
+ ListCell * lc ;
2269
+ AppendRelInfo * * appinfos ;
2270
+ int cnt = 0 ;
2271
+
2272
+ * nappinfos = bms_num_members (relids );
2273
+ appinfos = (AppendRelInfo * * ) palloc (sizeof (AppendRelInfo * ) * * nappinfos );
2274
+
2275
+ foreach (lc , root -> append_rel_list )
2276
+ {
2277
+ AppendRelInfo * appinfo = lfirst (lc );
2278
+
2279
+ if (bms_is_member (appinfo -> child_relid , relids ))
2280
+ {
2281
+ appinfos [cnt ] = appinfo ;
2282
+ cnt ++ ;
2283
+
2284
+ /* Stop when we have gathered all the AppendRelInfos. */
2285
+ if (cnt == * nappinfos )
2286
+ return appinfos ;
2287
+ }
2288
+ }
2289
+
2290
+ /* Should have found the entries ... */
2291
+ elog (ERROR , "did not find all requested child rels in append_rel_list" );
2292
+ return NULL ; /* not reached */
2170
2293
}
0 commit comments