| Line | Hits | Source | Commit |
| 1996 |
- |
fireRIRrules(Query *parsetree, List *activeRIRs) |
- |
| 1997 |
- |
{ |
- |
| 1998 |
- |
int origResultRelation = parsetree->resultRelation; |
- |
| 1999 |
- |
int rt_index; |
- |
| 2000 |
- |
ListCell *lc; |
- |
| 2001 |
- |
|
- |
| 2002 |
- |
/* |
- |
| 2003 |
- |
* Expand SEARCH and CYCLE clauses in CTEs. |
- |
| 2004 |
- |
* |
- |
| 2005 |
- |
* This is just a convenient place to do this, since we are already |
- |
| 2006 |
- |
* looking at each Query. |
- |
| 2007 |
- |
*/ |
- |
| 2008 |
- |
foreach(lc, parsetree->cteList) |
- |
| 2009 |
- |
{ |
- |
| 2010 |
- |
CommonTableExpr *cte = lfirst_node(CommonTableExpr, lc); |
- |
| 2011 |
- |
|
- |
| 2012 |
- |
if (cte->search_clause || cte->cycle_clause) |
- |
| 2013 |
- |
{ |
- |
| 2014 |
- |
cte = rewriteSearchAndCycle(cte); |
- |
| 2015 |
- |
lfirst(lc) = cte; |
- |
| 2016 |
- |
} |
- |
| 2017 |
- |
} |
- |
| 2018 |
- |
|
- |
| 2019 |
- |
/* |
- |
| 2020 |
- |
* don't try to convert this into a foreach loop, because rtable list can |
- |
| 2021 |
- |
* get changed each time through... |
- |
| 2022 |
- |
*/ |
- |
| 2023 |
- |
rt_index = 0; |
- |
| 2024 |
- |
while (rt_index < list_length(parsetree->rtable)) |
- |
| 2025 |
- |
{ |
- |
| 2026 |
- |
RangeTblEntry *rte; |
- |
| 2027 |
- |
Relation rel; |
- |
| 2028 |
- |
List *locks; |
- |
| 2029 |
- |
RuleLock *rules; |
- |
| 2030 |
- |
RewriteRule *rule; |
- |
| 2031 |
- |
int i; |
- |
| 2032 |
- |
|
- |
| 2033 |
- |
++rt_index; |
- |
| 2034 |
- |
|
- |
| 2035 |
- |
rte = rt_fetch(rt_index, parsetree->rtable); |
- |
| 2036 |
- |
|
- |
| 2037 |
- |
/* |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2038 |
- |
* Convert GRAPH_TABLE clause into a subquery using relational |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2039 |
- |
* operators. (This will change the rtekind to subquery, so it must |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2040 |
- |
* be done before the subquery handling below.) |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2041 |
- |
*/ |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2042 |
363946 |
if (rte->rtekind == RTE_GRAPH_TABLE) |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2043 |
- |
{ |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2044 |
349 |
parsetree = rewriteGraphTable(parsetree, rt_index); |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2045 |
- |
} |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2046 |
- |
|
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 2047 |
- |
/* |
- |
| 2048 |
- |
* A subquery RTE can't have associated rules, so there's nothing to |
- |
| 2049 |
- |
* do to this level of the query, but we must recurse into the |
- |
| 2050 |
- |
* subquery to expand any rule references in it. |
- |
| 2051 |
- |
*/ |
- |
| 2052 |
- |
if (rte->rtekind == RTE_SUBQUERY) |
- |
| 2053 |
- |
{ |
- |
| 2054 |
- |
rte->subquery = fireRIRrules(rte->subquery, activeRIRs); |
- |
| 2055 |
- |
|
- |
| 2056 |
- |
/* |
- |
| 2057 |
- |
* While we are here, make sure the query is marked as having row |
- |
| 2058 |
- |
* security if any of its subqueries do. |
- |
| 2059 |
- |
*/ |
- |
| 2060 |
- |
parsetree->hasRowSecurity |= rte->subquery->hasRowSecurity; |
- |
| 2061 |
- |
|
- |
| 2062 |
- |
continue; |
- |
| 2063 |
- |
} |
- |
| 2064 |
- |
|
- |
| 2065 |
- |
/* |
- |
| 2066 |
- |
* Joins and other non-relation RTEs can be ignored completely. |
- |
| 2067 |
- |
*/ |
- |
| 2068 |
- |
if (rte->rtekind != RTE_RELATION) |
- |
| 2069 |
- |
continue; |
- |
| 2070 |
- |
|
- |
| 2071 |
- |
/* |
- |
| 2072 |
- |
* Always ignore RIR rules for materialized views referenced in |
- |
| 2073 |
- |
* queries. (This does not prevent refreshing MVs, since they aren't |
- |
| 2074 |
- |
* referenced in their own query definitions.) |
- |
| 2075 |
- |
* |
- |
| 2076 |
- |
* Note: in the future we might want to allow MVs to be conditionally |
- |
| 2077 |
- |
* expanded as if they were regular views, if they are not scannable. |
- |
| 2078 |
- |
* In that case this test would need to be postponed till after we've |
- |
| 2079 |
- |
* opened the rel, so that we could check its state. |
- |
| 2080 |
- |
*/ |
- |
| 2081 |
- |
if (rte->relkind == RELKIND_MATVIEW) |
- |
| 2082 |
- |
continue; |
- |
| 2083 |
- |
|
- |
| 2084 |
- |
/* |
- |
| 2085 |
- |
* In INSERT ... ON CONFLICT, ignore the EXCLUDED pseudo-relation; |
- |
| 2086 |
- |
* even if it points to a view, we needn't expand it, and should not |
- |
| 2087 |
- |
* because we want the RTE to remain of RTE_RELATION type. Otherwise, |
- |
| 2088 |
- |
* it would get changed to RTE_SUBQUERY type, which is an |
- |
| 2089 |
- |
* untested/unsupported situation. |
- |
| 2090 |
- |
*/ |
- |
| 2091 |
- |
if (parsetree->onConflict && |
- |
| 2092 |
- |
rt_index == parsetree->onConflict->exclRelIndex) |
- |
| 2093 |
- |
continue; |
- |
| 2094 |
- |
|
- |
| 2095 |
- |
/* |
- |
| 2096 |
- |
* If the table is not referenced in the query, then we ignore it. |
- |
| 2097 |
- |
* This prevents infinite expansion loop due to new rtable entries |
- |
| 2098 |
- |
* inserted by expansion of a rule. A table is referenced if it is |
- |
| 2099 |
- |
* part of the join set (a source table), or is referenced by any Var |
- |
| 2100 |
- |
* nodes, or is the result table. |
- |
| 2101 |
- |
*/ |
- |
| 2102 |
- |
if (rt_index != parsetree->resultRelation && |
- |
| 2103 |
- |
!rangeTableEntry_used((Node *) parsetree, rt_index, 0)) |
- |
| 2104 |
- |
continue; |
- |
| 2105 |
- |
|
- |
| 2106 |
- |
/* |
- |
| 2107 |
- |
* Also, if this is a new result relation introduced by |
- |
| 2108 |
- |
* ApplyRetrieveRule, we don't want to do anything more with it. |
- |
| 2109 |
- |
*/ |
- |
| 2110 |
- |
if (rt_index == parsetree->resultRelation && |
- |
| 2111 |
- |
rt_index != origResultRelation) |
- |
| 2112 |
- |
continue; |
- |
| 2113 |
- |
|
- |
| 2114 |
- |
/* |
- |
| 2115 |
- |
* We can use NoLock here since either the parser or |
- |
| 2116 |
- |
* AcquireRewriteLocks should have locked the rel already. |
- |
| 2117 |
- |
*/ |
- |
| 2118 |
- |
rel = table_open(rte->relid, NoLock); |
- |
| 2119 |
- |
|
- |
| 2120 |
- |
/* |
- |
| 2121 |
- |
* Collect the RIR rules that we must apply |
- |
| 2122 |
- |
*/ |
- |
| 2123 |
- |
rules = rel->rd_rules; |
- |
| 2124 |
- |
if (rules != NULL) |
- |
| 2125 |
- |
{ |
- |
| 2126 |
- |
locks = NIL; |
- |
| 2127 |
- |
for (i = 0; i < rules->numLocks; i++) |
- |
| 2128 |
- |
{ |
- |
| 2129 |
- |
rule = rules->rules[i]; |
- |
| 2130 |
- |
if (rule->event != CMD_SELECT) |
- |
| 2131 |
- |
continue; |
- |
| 2132 |
- |
|
- |
| 2133 |
- |
locks = lappend(locks, rule); |
- |
| 2134 |
- |
} |
- |
| 2135 |
- |
|
- |
| 2136 |
- |
/* |
- |
| 2137 |
- |
* If we found any, apply them --- but first check for recursion! |
- |
| 2138 |
- |
*/ |
- |
| 2139 |
- |
if (locks != NIL) |
- |
| 2140 |
- |
{ |
- |
| 2141 |
- |
ListCell *l; |
- |
| 2142 |
- |
|
- |
| 2143 |
- |
if (list_member_oid(activeRIRs, RelationGetRelid(rel))) |
- |
| 2144 |
- |
ereport(ERROR, |
- |
| 2145 |
- |
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), |
- |
| 2146 |
- |
errmsg("infinite recursion detected in rules for relation \"%s\"", |
- |
| 2147 |
- |
RelationGetRelationName(rel)))); |
- |
| 2148 |
- |
activeRIRs = lappend_oid(activeRIRs, RelationGetRelid(rel)); |
- |
| 2149 |
- |
|
- |
| 2150 |
- |
foreach(l, locks) |
- |
| 2151 |
- |
{ |
- |
| 2152 |
- |
rule = lfirst(l); |
- |
| 2153 |
- |
|
- |
| 2154 |
- |
parsetree = ApplyRetrieveRule(parsetree, |
- |
| 2155 |
- |
rule, |
- |
| 2156 |
- |
rt_index, |
- |
| 2157 |
- |
rel, |
- |
| 2158 |
- |
activeRIRs); |
- |
| 2159 |
- |
} |
- |
| 2160 |
- |
|
- |
| 2161 |
- |
activeRIRs = list_delete_last(activeRIRs); |
- |
| 2162 |
- |
} |
- |
| 2163 |
- |
} |
- |
| 2164 |
- |
|
- |
| 2165 |
- |
table_close(rel, NoLock); |
- |
| 2166 |
- |
} |
- |
| 2167 |
- |
|
- |
| 2168 |
- |
/* Recurse into subqueries in WITH */ |
- |
| 2169 |
- |
foreach(lc, parsetree->cteList) |
- |
| 2170 |
- |
{ |
- |
| 2171 |
- |
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); |
- |
| 2172 |
- |
|
- |
| 2173 |
- |
cte->ctequery = (Node *) |
- |
| 2174 |
- |
fireRIRrules((Query *) cte->ctequery, activeRIRs); |
- |
| 2175 |
- |
|
- |
| 2176 |
- |
/* |
- |
| 2177 |
- |
* While we are here, make sure the query is marked as having row |
- |
| 2178 |
- |
* security if any of its CTEs do. |
- |
| 2179 |
- |
*/ |
- |
| 2180 |
- |
parsetree->hasRowSecurity |= ((Query *) cte->ctequery)->hasRowSecurity; |
- |
| 2181 |
- |
} |
- |
| 2182 |
- |
|
- |
| 2183 |
- |
/* |
- |
| 2184 |
- |
* Recurse into sublink subqueries, too. But we already did the ones in |
- |
| 2185 |
- |
* the rtable and cteList. |
- |
| 2186 |
- |
*/ |
- |
| 2187 |
- |
if (parsetree->hasSubLinks) |
- |
| 2188 |
- |
{ |
- |
| 2189 |
- |
fireRIRonSubLink_context context; |
- |
| 2190 |
- |
|
- |
| 2191 |
- |
context.activeRIRs = activeRIRs; |
- |
| 2192 |
- |
context.hasRowSecurity = false; |
- |
| 2193 |
- |
|
- |
| 2194 |
- |
query_tree_walker(parsetree, fireRIRonSubLink, &context, |
- |
| 2195 |
- |
QTW_IGNORE_RC_SUBQUERIES); |
- |
| 2196 |
- |
|
- |
| 2197 |
- |
/* |
- |
| 2198 |
- |
* Make sure the query is marked as having row security if any of its |
- |
| 2199 |
- |
* sublinks do. |
- |
| 2200 |
- |
*/ |
- |
| 2201 |
- |
parsetree->hasRowSecurity |= context.hasRowSecurity; |
- |
| 2202 |
- |
} |
- |
| 2203 |
- |
|
- |
| 2204 |
- |
/* |
- |
| 2205 |
- |
* Apply any row-level security policies. We do this last because it |
- |
| 2206 |
- |
* requires special recursion detection if the new quals have sublink |
- |
| 2207 |
- |
* subqueries, and if we did it in the loop above query_tree_walker would |
- |
| 2208 |
- |
* then recurse into those quals a second time. |
- |
| 2209 |
- |
*/ |
- |
| 2210 |
- |
rt_index = 0; |
- |
| 2211 |
- |
foreach(lc, parsetree->rtable) |
- |
| 2212 |
- |
{ |
- |
| 2213 |
- |
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); |
- |
| 2214 |
- |
Relation rel; |
- |
| 2215 |
- |
List *securityQuals; |
- |
| 2216 |
- |
List *withCheckOptions; |
- |
| 2217 |
- |
bool hasRowSecurity; |
- |
| 2218 |
- |
bool hasSubLinks; |
- |
| 2219 |
- |
|
- |
| 2220 |
- |
++rt_index; |
- |
| 2221 |
- |
|
- |
| 2222 |
- |
/* Only normal relations can have RLS policies */ |
- |
| 2223 |
- |
if (rte->rtekind != RTE_RELATION || |
- |
| 2224 |
- |
(rte->relkind != RELKIND_RELATION && |
- |
| 2225 |
- |
rte->relkind != RELKIND_PARTITIONED_TABLE)) |
- |
| 2226 |
- |
continue; |
- |
| 2227 |
- |
|
- |
| 2228 |
- |
rel = table_open(rte->relid, NoLock); |
- |
| 2229 |
- |
|
- |
| 2230 |
- |
/* |
- |
| 2231 |
- |
* Fetch any new security quals that must be applied to this RTE. |
- |
| 2232 |
- |
*/ |
- |
| 2233 |
- |
get_row_security_policies(parsetree, rte, rt_index, |
- |
| 2234 |
- |
&securityQuals, &withCheckOptions, |
- |
| 2235 |
- |
&hasRowSecurity, &hasSubLinks); |
- |
| 2236 |
- |
|
- |
| 2237 |
- |
if (securityQuals != NIL || withCheckOptions != NIL) |
- |
| 2238 |
- |
{ |
- |
| 2239 |
- |
if (hasSubLinks) |
- |
| 2240 |
- |
{ |
- |
| 2241 |
- |
acquireLocksOnSubLinks_context context; |
- |
| 2242 |
- |
fireRIRonSubLink_context fire_context; |
- |
| 2243 |
- |
|
- |
| 2244 |
- |
/* |
- |
| 2245 |
- |
* Recursively process the new quals, checking for infinite |
- |
| 2246 |
- |
* recursion. |
- |
| 2247 |
- |
*/ |
- |
| 2248 |
- |
if (list_member_oid(activeRIRs, RelationGetRelid(rel))) |
- |
| 2249 |
- |
ereport(ERROR, |
- |
| 2250 |
- |
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), |
- |
| 2251 |
- |
errmsg("infinite recursion detected in policy for relation \"%s\"", |
- |
| 2252 |
- |
RelationGetRelationName(rel)))); |
- |
| 2253 |
- |
|
- |
| 2254 |
- |
activeRIRs = lappend_oid(activeRIRs, RelationGetRelid(rel)); |
- |
| 2255 |
- |
|
- |
| 2256 |
- |
/* |
- |
| 2257 |
- |
* get_row_security_policies just passed back securityQuals |
- |
| 2258 |
- |
* and/or withCheckOptions, and there were SubLinks, make sure |
- |
| 2259 |
- |
* we lock any relations which are referenced. |
- |
| 2260 |
- |
* |
- |
| 2261 |
- |
* These locks would normally be acquired by the parser, but |
- |
| 2262 |
- |
* securityQuals and withCheckOptions are added post-parsing. |
- |
| 2263 |
- |
*/ |
- |
| 2264 |
- |
context.for_execute = true; |
- |
| 2265 |
- |
(void) acquireLocksOnSubLinks((Node *) securityQuals, &context); |
- |
| 2266 |
- |
(void) acquireLocksOnSubLinks((Node *) withCheckOptions, |
- |
| 2267 |
- |
&context); |
- |
| 2268 |
- |
|
- |
| 2269 |
- |
/* |
- |
| 2270 |
- |
* Now that we have the locks on anything added by |
- |
| 2271 |
- |
* get_row_security_policies, fire any RIR rules for them. |
- |
| 2272 |
- |
*/ |
- |
| 2273 |
- |
fire_context.activeRIRs = activeRIRs; |
- |
| 2274 |
- |
fire_context.hasRowSecurity = false; |
- |
| 2275 |
- |
|
- |
| 2276 |
- |
expression_tree_walker((Node *) securityQuals, |
- |
| 2277 |
- |
fireRIRonSubLink, &fire_context); |
- |
| 2278 |
- |
|
- |
| 2279 |
- |
expression_tree_walker((Node *) withCheckOptions, |
- |
| 2280 |
- |
fireRIRonSubLink, &fire_context); |
- |
| 2281 |
- |
|
- |
| 2282 |
- |
/* |
- |
| 2283 |
- |
* We can ignore the value of fire_context.hasRowSecurity |
- |
| 2284 |
- |
* since we only reach this code in cases where hasRowSecurity |
- |
| 2285 |
- |
* is already true. |
- |
| 2286 |
- |
*/ |
- |
| 2287 |
- |
Assert(hasRowSecurity); |
- |
| 2288 |
- |
|
- |
| 2289 |
- |
activeRIRs = list_delete_last(activeRIRs); |
- |
| 2290 |
- |
} |
- |
| 2291 |
- |
|
- |
| 2292 |
- |
/* |
- |
| 2293 |
- |
* Add the new security barrier quals to the start of the RTE's |
- |
| 2294 |
- |
* list so that they get applied before any existing barrier quals |
- |
| 2295 |
- |
* (which would have come from a security-barrier view, and should |
- |
| 2296 |
- |
* get lower priority than RLS conditions on the table itself). |
- |
| 2297 |
- |
*/ |
- |
| 2298 |
- |
rte->securityQuals = list_concat(securityQuals, |
- |
| 2299 |
- |
rte->securityQuals); |
- |
| 2300 |
- |
|
- |
| 2301 |
- |
parsetree->withCheckOptions = list_concat(withCheckOptions, |
- |
| 2302 |
- |
parsetree->withCheckOptions); |
- |
| 2303 |
- |
} |
- |
| 2304 |
- |
|
- |
| 2305 |
- |
/* |
- |
| 2306 |
- |
* Make sure the query is marked correctly if row-level security |
- |
| 2307 |
- |
* applies, or if the new quals had sublinks. |
- |
| 2308 |
- |
*/ |
- |
| 2309 |
- |
if (hasRowSecurity) |
- |
| 2310 |
- |
parsetree->hasRowSecurity = true; |
- |
| 2311 |
- |
if (hasSubLinks) |
- |
| 2312 |
- |
parsetree->hasSubLinks = true; |
- |
| 2313 |
- |
|
- |
| 2314 |
- |
table_close(rel, NoLock); |
- |
| 2315 |
- |
} |
- |
| 2316 |
- |
|
- |
| 2317 |
- |
return parsetree; |
- |
| 2318 |
- |
} |
- |