1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* rewriteManip.h
|
2001-06-13 20:56:30 +02:00
|
|
|
* Querytree manipulation subroutines for query rewriter.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/include/rewrite/rewriteManip.h
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#ifndef REWRITEMANIP_H
|
|
|
|
#define REWRITEMANIP_H
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-06-13 20:56:30 +02:00
|
|
|
#include "nodes/parsenodes.h"
|
|
|
|
|
1997-11-26 02:14:33 +01:00
|
|
|
|
Fix subquery pullup to wrap a PlaceHolderVar around the entire RowExpr
that's generated for a whole-row Var referencing the subquery, when the
subquery is in the nullable side of an outer join. The previous coding
instead put PlaceHolderVars around the elements of the RowExpr. The effect
was that when the outer join made the subquery outputs go to null, the
whole-row Var produced ROW(NULL,NULL,...) rather than just NULL. There
are arguments afoot about whether those things ought to be semantically
indistinguishable, but for the moment they are not entirely so, and the
planner needs to take care that its machinations preserve the difference.
Per bug #5025.
Making this feasible required refactoring ResolveNew() to allow more caller
control over what is substituted for a Var. I chose to make ResolveNew()
a wrapper around a new general-purpose function replace_rte_variables().
I also fixed the ancient bogosity that ResolveNew might fail to set
a query's hasSubLinks field after inserting a SubLink in it. Although
all current callers make sure that happens anyway, we've had bugs of that
sort before, and it seemed like a good time to install a proper solution.
Back-patch to 8.4. The problem can be demonstrated clear back to 8.0,
but the fix would be too invasive in earlier branches; not to mention
that people may be depending on the subtly-incorrect behavior. The
8.4 series is new enough that fixing this probably won't cause complaints,
but it might in older branches. Also, 8.4 shows the incorrect behavior
in more cases than older branches do, because it is able to flatten
subqueries in more cases.
2009-09-02 19:52:24 +02:00
|
|
|
typedef struct replace_rte_variables_context replace_rte_variables_context;
|
|
|
|
|
2010-02-26 03:01:40 +01:00
|
|
|
typedef Node *(*replace_rte_variables_callback) (Var *var,
|
|
|
|
replace_rte_variables_context *context);
|
Fix subquery pullup to wrap a PlaceHolderVar around the entire RowExpr
that's generated for a whole-row Var referencing the subquery, when the
subquery is in the nullable side of an outer join. The previous coding
instead put PlaceHolderVars around the elements of the RowExpr. The effect
was that when the outer join made the subquery outputs go to null, the
whole-row Var produced ROW(NULL,NULL,...) rather than just NULL. There
are arguments afoot about whether those things ought to be semantically
indistinguishable, but for the moment they are not entirely so, and the
planner needs to take care that its machinations preserve the difference.
Per bug #5025.
Making this feasible required refactoring ResolveNew() to allow more caller
control over what is substituted for a Var. I chose to make ResolveNew()
a wrapper around a new general-purpose function replace_rte_variables().
I also fixed the ancient bogosity that ResolveNew might fail to set
a query's hasSubLinks field after inserting a SubLink in it. Although
all current callers make sure that happens anyway, we've had bugs of that
sort before, and it seemed like a good time to install a proper solution.
Back-patch to 8.4. The problem can be demonstrated clear back to 8.0,
but the fix would be too invasive in earlier branches; not to mention
that people may be depending on the subtly-incorrect behavior. The
8.4 series is new enough that fixing this probably won't cause complaints,
but it might in older branches. Also, 8.4 shows the incorrect behavior
in more cases than older branches do, because it is able to flatten
subqueries in more cases.
2009-09-02 19:52:24 +02:00
|
|
|
|
|
|
|
struct replace_rte_variables_context
|
|
|
|
{
|
|
|
|
replace_rte_variables_callback callback; /* callback function */
|
2010-02-26 03:01:40 +01:00
|
|
|
void *callback_arg; /* context data for callback function */
|
|
|
|
int target_varno; /* RTE index to search for */
|
|
|
|
int sublevels_up; /* (current) nesting depth */
|
|
|
|
bool inserted_sublink; /* have we inserted a SubLink? */
|
Fix subquery pullup to wrap a PlaceHolderVar around the entire RowExpr
that's generated for a whole-row Var referencing the subquery, when the
subquery is in the nullable side of an outer join. The previous coding
instead put PlaceHolderVars around the elements of the RowExpr. The effect
was that when the outer join made the subquery outputs go to null, the
whole-row Var produced ROW(NULL,NULL,...) rather than just NULL. There
are arguments afoot about whether those things ought to be semantically
indistinguishable, but for the moment they are not entirely so, and the
planner needs to take care that its machinations preserve the difference.
Per bug #5025.
Making this feasible required refactoring ResolveNew() to allow more caller
control over what is substituted for a Var. I chose to make ResolveNew()
a wrapper around a new general-purpose function replace_rte_variables().
I also fixed the ancient bogosity that ResolveNew might fail to set
a query's hasSubLinks field after inserting a SubLink in it. Although
all current callers make sure that happens anyway, we've had bugs of that
sort before, and it seemed like a good time to install a proper solution.
Back-patch to 8.4. The problem can be demonstrated clear back to 8.0,
but the fix would be too invasive in earlier branches; not to mention
that people may be depending on the subtly-incorrect behavior. The
8.4 series is new enough that fixing this probably won't cause complaints,
but it might in older branches. Also, 8.4 shows the incorrect behavior
in more cases than older branches do, because it is able to flatten
subqueries in more cases.
2009-09-02 19:52:24 +02:00
|
|
|
};
|
|
|
|
|
2012-11-08 22:52:49 +01:00
|
|
|
typedef enum ReplaceVarsNoMatchOption
|
|
|
|
{
|
|
|
|
REPLACEVARS_REPORT_ERROR, /* throw error if no match */
|
|
|
|
REPLACEVARS_CHANGE_VARNO, /* change the Var's varno, nothing else */
|
2013-05-29 22:58:43 +02:00
|
|
|
REPLACEVARS_SUBSTITUTE_NULL /* replace with a NULL Const */
|
2012-11-08 22:52:49 +01:00
|
|
|
} ReplaceVarsNoMatchOption;
|
|
|
|
|
Fix subquery pullup to wrap a PlaceHolderVar around the entire RowExpr
that's generated for a whole-row Var referencing the subquery, when the
subquery is in the nullable side of an outer join. The previous coding
instead put PlaceHolderVars around the elements of the RowExpr. The effect
was that when the outer join made the subquery outputs go to null, the
whole-row Var produced ROW(NULL,NULL,...) rather than just NULL. There
are arguments afoot about whether those things ought to be semantically
indistinguishable, but for the moment they are not entirely so, and the
planner needs to take care that its machinations preserve the difference.
Per bug #5025.
Making this feasible required refactoring ResolveNew() to allow more caller
control over what is substituted for a Var. I chose to make ResolveNew()
a wrapper around a new general-purpose function replace_rte_variables().
I also fixed the ancient bogosity that ResolveNew might fail to set
a query's hasSubLinks field after inserting a SubLink in it. Although
all current callers make sure that happens anyway, we've had bugs of that
sort before, and it seemed like a good time to install a proper solution.
Back-patch to 8.4. The problem can be demonstrated clear back to 8.0,
but the fix would be too invasive in earlier branches; not to mention
that people may be depending on the subtly-incorrect behavior. The
8.4 series is new enough that fixing this probably won't cause complaints,
but it might in older branches. Also, 8.4 shows the incorrect behavior
in more cases than older branches do, because it is able to flatten
subqueries in more cases.
2009-09-02 19:52:24 +02:00
|
|
|
|
1999-10-01 06:08:24 +02:00
|
|
|
extern void OffsetVarNodes(Node *node, int offset, int sublevels_up);
|
|
|
|
extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
|
2000-04-12 19:17:23 +02:00
|
|
|
int sublevels_up);
|
2000-03-16 04:23:18 +01:00
|
|
|
extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
|
2000-04-12 19:17:23 +02:00
|
|
|
int min_sublevels_up);
|
2008-08-14 22:31:29 +02:00
|
|
|
extern void IncrementVarSublevelsUp_rtable(List *rtable,
|
2009-06-11 16:49:15 +02:00
|
|
|
int delta_sublevels_up, int min_sublevels_up);
|
2000-09-12 23:07:18 +02:00
|
|
|
|
|
|
|
extern bool rangeTableEntry_used(Node *node, int rt_index,
|
2001-03-22 05:01:46 +01:00
|
|
|
int sublevels_up);
|
2000-09-12 23:07:18 +02:00
|
|
|
|
2000-12-05 20:15:10 +01:00
|
|
|
extern Query *getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr);
|
|
|
|
|
1999-10-01 06:08:24 +02:00
|
|
|
extern void AddQual(Query *parsetree, Node *qual);
|
2002-10-20 02:58:55 +02:00
|
|
|
extern void AddInvertedQual(Query *parsetree, Node *qual);
|
1998-07-19 07:49:26 +02:00
|
|
|
|
2008-08-22 02:16:04 +02:00
|
|
|
extern bool contain_aggs_of_level(Node *node, int levelsup);
|
2008-09-01 22:42:46 +02:00
|
|
|
extern int locate_agg_of_level(Node *node, int levelsup);
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
extern bool contain_windowfuncs(Node *node);
|
2008-12-28 19:54:01 +01:00
|
|
|
extern int locate_windowfunc(Node *node);
|
2000-03-16 04:23:18 +01:00
|
|
|
extern bool checkExprHasSubLink(Node *node);
|
|
|
|
|
Fix subquery pullup to wrap a PlaceHolderVar around the entire RowExpr
that's generated for a whole-row Var referencing the subquery, when the
subquery is in the nullable side of an outer join. The previous coding
instead put PlaceHolderVars around the elements of the RowExpr. The effect
was that when the outer join made the subquery outputs go to null, the
whole-row Var produced ROW(NULL,NULL,...) rather than just NULL. There
are arguments afoot about whether those things ought to be semantically
indistinguishable, but for the moment they are not entirely so, and the
planner needs to take care that its machinations preserve the difference.
Per bug #5025.
Making this feasible required refactoring ResolveNew() to allow more caller
control over what is substituted for a Var. I chose to make ResolveNew()
a wrapper around a new general-purpose function replace_rte_variables().
I also fixed the ancient bogosity that ResolveNew might fail to set
a query's hasSubLinks field after inserting a SubLink in it. Although
all current callers make sure that happens anyway, we've had bugs of that
sort before, and it seemed like a good time to install a proper solution.
Back-patch to 8.4. The problem can be demonstrated clear back to 8.0,
but the fix would be too invasive in earlier branches; not to mention
that people may be depending on the subtly-incorrect behavior. The
8.4 series is new enough that fixing this probably won't cause complaints,
but it might in older branches. Also, 8.4 shows the incorrect behavior
in more cases than older branches do, because it is able to flatten
subqueries in more cases.
2009-09-02 19:52:24 +02:00
|
|
|
extern Node *replace_rte_variables(Node *node,
|
|
|
|
int target_varno, int sublevels_up,
|
|
|
|
replace_rte_variables_callback callback,
|
|
|
|
void *callback_arg,
|
|
|
|
bool *outer_hasSubLinks);
|
|
|
|
extern Node *replace_rte_variables_mutator(Node *node,
|
|
|
|
replace_rte_variables_context *context);
|
|
|
|
|
Prevent CREATE TABLE LIKE/INHERITS from (mis) copying whole-row Vars.
If a CHECK constraint or index definition contained a whole-row Var (that
is, "table.*"), an attempt to copy that definition via CREATE TABLE LIKE or
table inheritance produced incorrect results: the copied Var still claimed
to have the rowtype of the source table, rather than the created table.
For the LIKE case, it seems reasonable to just throw error for this
situation, since the point of LIKE is that the new table is not permanently
coupled to the old, so there's no reason to assume its rowtype will stay
compatible. In the inheritance case, we should ideally allow such
constraints, but doing so will require nontrivial refactoring of CREATE
TABLE processing (because we'd need to know the OID of the new table's
rowtype before we adjust inherited CHECK constraints). In view of the lack
of previous complaints, that doesn't seem worth the risk in a back-patched
bug fix, so just make it throw error for the inheritance case as well.
Along the way, replace change_varattnos_of_a_node() with a more robust
function map_variable_attnos(), which is capable of being extended to
handle insertion of ConvertRowtypeExpr whenever we get around to fixing
the inheritance case nicely, and in the meantime it returns a failure
indication to the caller so that a helpful message with some context can be
thrown. Also, this code will do the right thing with subselects (if we
ever allow them in CHECK or indexes), and it range-checks varattnos before
using them to index into the map array.
Per report from Sergey Konoplev. Back-patch to all supported branches.
2012-06-30 22:43:50 +02:00
|
|
|
extern Node *map_variable_attnos(Node *node,
|
|
|
|
int target_varno, int sublevels_up,
|
|
|
|
const AttrNumber *attno_map, int map_length,
|
|
|
|
bool *found_whole_row);
|
|
|
|
|
2012-11-08 22:52:49 +01:00
|
|
|
extern Node *ReplaceVarsFromTargetList(Node *node,
|
|
|
|
int target_varno, int sublevels_up,
|
|
|
|
RangeTblEntry *target_rte,
|
|
|
|
List *targetlist,
|
|
|
|
ReplaceVarsNoMatchOption nomatch_option,
|
|
|
|
int nomatch_varno,
|
|
|
|
bool *outer_hasSubLinks);
|
2001-10-28 07:26:15 +01:00
|
|
|
|
2001-11-05 18:46:40 +01:00
|
|
|
#endif /* REWRITEMANIP_H */
|