diff options
Diffstat (limited to 'src/backend/rewrite/rewriteManip.c')
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 954e21af181..2b6c01fc8f6 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.118 2008/11/15 19:43:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.119 2008/12/28 18:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,10 +34,18 @@ typedef struct int sublevels_up; } locate_agg_of_level_context; +typedef struct +{ + int win_location; +} locate_windowfunc_context; + static bool contain_aggs_of_level_walker(Node *node, contain_aggs_of_level_context *context); static bool locate_agg_of_level_walker(Node *node, locate_agg_of_level_context *context); +static bool contain_windowfuncs_walker(Node *node, void *context); +static bool locate_windowfunc_walker(Node *node, + locate_windowfunc_context *context); static bool checkExprHasSubLink_walker(Node *node, void *context); static Relids offset_relid_set(Relids relids, int offset); static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); @@ -176,6 +184,87 @@ locate_agg_of_level_walker(Node *node, } /* + * checkExprHasWindowFuncs - + * Check if an expression contains a window function call of the + * current query level. + */ +bool +checkExprHasWindowFuncs(Node *node) +{ + /* + * Must be prepared to start with a Query or a bare expression tree; if + * it's a Query, we don't want to increment sublevels_up. + */ + return query_or_expression_tree_walker(node, + contain_windowfuncs_walker, + NULL, + 0); +} + +static bool +contain_windowfuncs_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + if (IsA(node, WindowFunc)) + return true; /* abort the tree traversal and return true */ + /* Mustn't recurse into subselects */ + return expression_tree_walker(node, contain_windowfuncs_walker, + (void *) context); +} + +/* + * locate_windowfunc - + * Find the parse location of any windowfunc of the current query level. + * + * Returns -1 if no such windowfunc is in the querytree, or if they all have + * unknown parse location. (The former case is probably caller error, + * but we don't bother to distinguish it from the latter case.) + * + * Note: it might seem appropriate to merge this functionality into + * contain_windowfuncs, but that would complicate that function's API. + * Currently, the only uses of this function are for error reporting, + * and so shaving cycles probably isn't very important. + */ +int +locate_windowfunc(Node *node) +{ + locate_windowfunc_context context; + + context.win_location = -1; /* in case we find nothing */ + + /* + * Must be prepared to start with a Query or a bare expression tree; if + * it's a Query, we don't want to increment sublevels_up. + */ + (void) query_or_expression_tree_walker(node, + locate_windowfunc_walker, + (void *) &context, + 0); + + return context.win_location; +} + +static bool +locate_windowfunc_walker(Node *node, locate_windowfunc_context *context) +{ + if (node == NULL) + return false; + if (IsA(node, WindowFunc)) + { + if (((WindowFunc *) node)->location >= 0) + { + context->win_location = ((WindowFunc *) node)->location; + return true; /* abort the tree traversal and return true */ + } + /* else fall through to examine argument */ + } + /* Mustn't recurse into subselects */ + return expression_tree_walker(node, locate_windowfunc_walker, + (void *) context); +} + +/* * checkExprHasSubLink - * Check if an expression contains a SubLink. */ @@ -1023,6 +1112,7 @@ AddInvertedQual(Query *parsetree, Node *qual) * Messy, isn't it? We do not need to do similar pushups for hasAggs, * because it isn't possible for this transformation to insert a level-zero * aggregate reference into a subquery --- it could only insert outer aggs. + * Likewise for hasWindowFuncs. */ typedef struct |