diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-10 16:23:40 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-10 16:23:52 -0500 |
commit | c82c92b111b7b636e80f8a432de10c62011b35b6 (patch) | |
tree | cf0accbfe09768c55fbd19b41707f5b2c0d835af /src/backend/optimizer/util/var.c | |
parent | fd31cd265138019dcccc9b5fe53043670898bc9f (diff) | |
download | postgresql-c82c92b111b7b636e80f8a432de10c62011b35b6.tar.gz postgresql-c82c92b111b7b636e80f8a432de10c62011b35b6.zip |
Give pull_var_clause() reject/recurse/return behavior for WindowFuncs too.
All along, this function should have treated WindowFuncs in a manner
similar to Aggrefs, ie with an option whether or not to recurse into them.
By not considering the case, it was always recursing, which is OK for most
callers (although I suspect that the case in prepare_sort_from_pathkeys
might represent a bug). But now we need return-without-recursing behavior
as well. There are also more than a few callers that should never see a
WindowFunc, and now we'll get some error checking on that.
Diffstat (limited to 'src/backend/optimizer/util/var.c')
-rw-r--r-- | src/backend/optimizer/util/var.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index a389f42a224..292e1f4aac3 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -503,6 +503,13 @@ locate_var_of_level_walker(Node *node, * Vars within an Aggref's expression are included in the result only * when PVC_RECURSE_AGGREGATES is specified. * + * WindowFuncs are handled according to these bits in 'flags': + * PVC_INCLUDE_WINDOWFUNCS include WindowFuncs in output list + * PVC_RECURSE_WINDOWFUNCS recurse into WindowFunc arguments + * neither flag throw error if WindowFunc found + * Vars within a WindowFunc's expression are included in the result only + * when PVC_RECURSE_WINDOWFUNCS is specified. + * * PlaceHolderVars are handled according to these bits in 'flags': * PVC_INCLUDE_PLACEHOLDERS include PlaceHolderVars in output list * PVC_RECURSE_PLACEHOLDERS recurse into PlaceHolderVar arguments @@ -532,6 +539,8 @@ pull_var_clause(Node *node, int flags) /* Assert that caller has not specified inconsistent flags */ Assert((flags & (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES)) != (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES)); + Assert((flags & (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS)) + != (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS)); Assert((flags & (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS)) != (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS)); @@ -594,6 +603,22 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) else elog(ERROR, "GROUPING found where not expected"); } + else if (IsA(node, WindowFunc)) + { + /* WindowFuncs have no levelsup field to check ... */ + if (context->flags & PVC_INCLUDE_WINDOWFUNCS) + { + context->varlist = lappend(context->varlist, node); + /* we do NOT descend into the contained expressions */ + return false; + } + else if (context->flags & PVC_RECURSE_WINDOWFUNCS) + { + /* fall through to recurse into the windowfunc's arguments */ + } + else + elog(ERROR, "WindowFunc found where not expected"); + } else if (IsA(node, PlaceHolderVar)) { if (((PlaceHolderVar *) node)->phlevelsup != 0) |