* check_output_expressions - check subquery's output expressions for safety * * There are several cases in which it's unsafe to push down an upper-level * qual if it references a particular output column of a subquery. We check * each output column of the subquery and set unsafeColumns[k] to true if * that column is unsafe for a pushed-down qual to reference. The conditions * checked here
| 4208 | * subquery_is_pushdown_safe handles that.) |
| 4209 | */ |
| 4210 | static void |
| 4211 | check_output_expressions(Query *subquery, pushdown_safety_info *safetyInfo) |
| 4212 | { |
| 4213 | ListCell *lc; |
| 4214 | |
| 4215 | foreach(lc, subquery->targetList) |
| 4216 | { |
| 4217 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 4218 | |
| 4219 | if (tle->resjunk) |
| 4220 | continue; /* ignore resjunk columns */ |
| 4221 | |
| 4222 | /* We need not check further if output col is already known unsafe */ |
| 4223 | if (safetyInfo->unsafeColumns[tle->resno]) |
| 4224 | continue; |
| 4225 | |
| 4226 | /* Functions returning sets are unsafe (point 1) */ |
| 4227 | if (subquery->hasTargetSRFs && |
| 4228 | expression_returns_set((Node *) tle->expr)) |
| 4229 | { |
| 4230 | safetyInfo->unsafeColumns[tle->resno] = true; |
| 4231 | continue; |
| 4232 | } |
| 4233 | |
| 4234 | /* Volatile functions are unsafe (point 2) */ |
| 4235 | if (contain_volatile_functions((Node *) tle->expr)) |
| 4236 | { |
| 4237 | safetyInfo->unsafeColumns[tle->resno] = true; |
| 4238 | continue; |
| 4239 | } |
| 4240 | |
| 4241 | /* If subquery uses DISTINCT ON, check point 3 */ |
| 4242 | if (subquery->hasDistinctOn && |
| 4243 | !targetIsInSortList(tle, InvalidOid, subquery->distinctClause)) |
| 4244 | { |
| 4245 | /* non-DISTINCT column, so mark it unsafe */ |
| 4246 | safetyInfo->unsafeColumns[tle->resno] = true; |
| 4247 | continue; |
| 4248 | } |
| 4249 | |
| 4250 | /* If subquery uses window functions, check point 4 */ |
| 4251 | if (subquery->hasWindowFuncs && |
| 4252 | !targetIsInAllPartitionLists(tle, subquery)) |
| 4253 | { |
| 4254 | /* not present in all PARTITION BY clauses, so mark it unsafe */ |
| 4255 | safetyInfo->unsafeColumns[tle->resno] = true; |
| 4256 | continue; |
| 4257 | } |
| 4258 | |
| 4259 | /* Refuse subplans */ |
| 4260 | if (contain_subplans((Node *) tle->expr)) |
| 4261 | { |
| 4262 | safetyInfo->unsafeColumns[tle->resno] = true; |
| 4263 | continue; |
| 4264 | } |
| 4265 | } |
| 4266 | } |
| 4267 |
no test coverage detected