#include "postgres.h"#include "access/sysattr.h"#include "nodes/nodeFuncs.h"#include "optimizer/prep.h"#include "optimizer/var.h"#include "parser/parsetree.h"#include "rewrite/rewriteManip.h"
Go to the source code of this file.
| static Relids alias_relid_set | ( | PlannerInfo * | root, | |
| Relids | relids | |||
| ) | [static] |
Definition at line 764 of file var.c.
References bms_add_member(), bms_copy(), bms_first_member(), bms_free(), bms_join(), get_relids_for_join(), PlannerInfo::parse, rt_fetch, Query::rtable, RTE_JOIN, and RangeTblEntry::rtekind.
Referenced by flatten_join_alias_vars_mutator().
{
Relids result = NULL;
Relids tmprelids;
int rtindex;
tmprelids = bms_copy(relids);
while ((rtindex = bms_first_member(tmprelids)) >= 0)
{
RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
if (rte->rtekind == RTE_JOIN)
result = bms_join(result, get_relids_for_join(root, rtindex));
else
result = bms_add_member(result, rtindex);
}
bms_free(tmprelids);
return result;
}
Definition at line 324 of file var.c.
References contain_var_clause_walker(), and NULL.
Referenced by cookDefault(), domainAddConstraint(), examine_parameter_list(), is_pseudo_constant_clause(), and match_clause_to_ordering_op().
{
return contain_var_clause_walker(node, NULL);
}
Definition at line 330 of file var.c.
References expression_tree_walker(), IsA, and NULL.
Referenced by contain_var_clause().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
if (((Var *) node)->varlevelsup == 0)
return true; /* abort the tree traversal and return true */
return false;
}
if (IsA(node, CurrentOfExpr))
return true;
if (IsA(node, PlaceHolderVar))
{
if (((PlaceHolderVar *) node)->phlevelsup == 0)
return true; /* abort the tree traversal and return true */
/* else fall through to check the contained expr */
}
return expression_tree_walker(node, contain_var_clause_walker, context);
}
Definition at line 362 of file var.c.
References contain_vars_of_level_walker(), and query_or_expression_tree_walker().
Referenced by checkExprIsVarFree(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), convert_EXISTS_to_ANY(), make_restrictinfos_from_actual_clauses(), pullup_replace_vars_callback(), transformAExprIn(), transformRangeFunction(), transformSetOperationTree(), and transformValuesClause().
{
int sublevels_up = levelsup;
return query_or_expression_tree_walker(node,
contain_vars_of_level_walker,
(void *) &sublevels_up,
0);
}
Definition at line 373 of file var.c.
References expression_tree_walker(), IsA, NULL, and query_tree_walker().
Referenced by contain_vars_of_level().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
if (((Var *) node)->varlevelsup == *sublevels_up)
return true; /* abort tree traversal and return true */
return false;
}
if (IsA(node, CurrentOfExpr))
{
if (*sublevels_up == 0)
return true;
return false;
}
if (IsA(node, PlaceHolderVar))
{
if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up)
return true; /* abort the tree traversal and return true */
/* else fall through to check the contained expr */
}
if (IsA(node, Query))
{
/* Recurse into subselects */
bool result;
(*sublevels_up)++;
result = query_tree_walker((Query *) node,
contain_vars_of_level_walker,
(void *) sublevels_up,
0);
(*sublevels_up)--;
return result;
}
return expression_tree_walker(node,
contain_vars_of_level_walker,
(void *) sublevels_up);
}
| Node* flatten_join_alias_vars | ( | PlannerInfo * | root, | |
| Node * | node | |||
| ) |
Definition at line 608 of file var.c.
References flatten_join_alias_vars_mutator(), Query::hasSubLinks, flatten_join_alias_vars_context::inserted_sublink, PlannerInfo::parse, flatten_join_alias_vars_context::possible_sublink, flatten_join_alias_vars_context::root, and flatten_join_alias_vars_context::sublevels_up.
Referenced by parseCheckAggregates(), preprocess_expression(), and subquery_planner().
{
flatten_join_alias_vars_context context;
context.root = root;
context.sublevels_up = 0;
/* flag whether join aliases could possibly contain SubLinks */
context.possible_sublink = root->parse->hasSubLinks;
/* if hasSubLinks is already true, no need to work hard */
context.inserted_sublink = root->parse->hasSubLinks;
return flatten_join_alias_vars_mutator(node, &context);
}
| static Node * flatten_join_alias_vars_mutator | ( | Node * | node, | |
| flatten_join_alias_vars_context * | context | |||
| ) | [static] |
Definition at line 623 of file var.c.
References alias_relid_set(), RowExpr::args, Assert, checkExprHasSubLink(), RowExpr::colnames, Alias::colnames, copyObject(), RangeTblEntry::eref, expression_tree_mutator(), forboth, Query::hasSubLinks, IncrementVarSublevelsUp(), flatten_join_alias_vars_context::inserted_sublink, InvalidAttrNumber, IsA, RangeTblEntry::joinaliasvars, lappend(), lfirst, list_length(), list_nth(), RowExpr::location, Var::location, makeNode, NULL, PlannerInfo::parse, PlaceHolderVar::phlevelsup, PlaceHolderVar::phrels, flatten_join_alias_vars_context::possible_sublink, QTW_IGNORE_JOINALIASES, query_tree_mutator(), flatten_join_alias_vars_context::root, RowExpr::row_format, RowExpr::row_typeid, rt_fetch, Query::rtable, RTE_JOIN, RangeTblEntry::rtekind, flatten_join_alias_vars_context::sublevels_up, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.
Referenced by flatten_join_alias_vars().
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
{
Var *var = (Var *) node;
RangeTblEntry *rte;
Node *newvar;
/* No change unless Var belongs to a JOIN of the target level */
if (var->varlevelsup != context->sublevels_up)
return node; /* no need to copy, really */
rte = rt_fetch(var->varno, context->root->parse->rtable);
if (rte->rtekind != RTE_JOIN)
return node;
if (var->varattno == InvalidAttrNumber)
{
/* Must expand whole-row reference */
RowExpr *rowexpr;
List *fields = NIL;
List *colnames = NIL;
AttrNumber attnum;
ListCell *lv;
ListCell *ln;
attnum = 0;
Assert(list_length(rte->joinaliasvars) == list_length(rte->eref->colnames));
forboth(lv, rte->joinaliasvars, ln, rte->eref->colnames)
{
newvar = (Node *) lfirst(lv);
attnum++;
/* Ignore dropped columns */
if (IsA(newvar, Const))
continue;
newvar = copyObject(newvar);
/*
* If we are expanding an alias carried down from an upper
* query, must adjust its varlevelsup fields.
*/
if (context->sublevels_up != 0)
IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
/* Preserve original Var's location, if possible */
if (IsA(newvar, Var))
((Var *) newvar)->location = var->location;
/* Recurse in case join input is itself a join */
/* (also takes care of setting inserted_sublink if needed) */
newvar = flatten_join_alias_vars_mutator(newvar, context);
fields = lappend(fields, newvar);
/* We need the names of non-dropped columns, too */
colnames = lappend(colnames, copyObject((Node *) lfirst(ln)));
}
rowexpr = makeNode(RowExpr);
rowexpr->args = fields;
rowexpr->row_typeid = var->vartype;
rowexpr->row_format = COERCE_IMPLICIT_CAST;
rowexpr->colnames = colnames;
rowexpr->location = var->location;
return (Node *) rowexpr;
}
/* Expand join alias reference */
Assert(var->varattno > 0);
newvar = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
newvar = copyObject(newvar);
/*
* If we are expanding an alias carried down from an upper query, must
* adjust its varlevelsup fields.
*/
if (context->sublevels_up != 0)
IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
/* Preserve original Var's location, if possible */
if (IsA(newvar, Var))
((Var *) newvar)->location = var->location;
/* Recurse in case join input is itself a join */
newvar = flatten_join_alias_vars_mutator(newvar, context);
/* Detect if we are adding a sublink to query */
if (context->possible_sublink && !context->inserted_sublink)
context->inserted_sublink = checkExprHasSubLink(newvar);
return newvar;
}
if (IsA(node, PlaceHolderVar))
{
/* Copy the PlaceHolderVar node with correct mutation of subnodes */
PlaceHolderVar *phv;
phv = (PlaceHolderVar *) expression_tree_mutator(node,
flatten_join_alias_vars_mutator,
(void *) context);
/* now fix PlaceHolderVar's relid sets */
if (phv->phlevelsup == context->sublevels_up)
{
phv->phrels = alias_relid_set(context->root,
phv->phrels);
}
return (Node *) phv;
}
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *newnode;
bool save_inserted_sublink;
context->sublevels_up++;
save_inserted_sublink = context->inserted_sublink;
context->inserted_sublink = ((Query *) node)->hasSubLinks;
newnode = query_tree_mutator((Query *) node,
flatten_join_alias_vars_mutator,
(void *) context,
QTW_IGNORE_JOINALIASES);
newnode->hasSubLinks |= context->inserted_sublink;
context->inserted_sublink = save_inserted_sublink;
context->sublevels_up--;
return (Node *) newnode;
}
/* Already-planned tree not supported */
Assert(!IsA(node, SubPlan));
/* Shouldn't need to handle these planner auxiliary nodes here */
Assert(!IsA(node, SpecialJoinInfo));
Assert(!IsA(node, LateralJoinInfo));
Assert(!IsA(node, PlaceHolderInfo));
Assert(!IsA(node, MinMaxAggInfo));
return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
(void *) context);
}
| int locate_var_of_level | ( | Node * | node, | |
| int | levelsup | |||
| ) |
Definition at line 430 of file var.c.
References locate_var_of_level_walker(), query_or_expression_tree_walker(), locate_var_of_level_context::sublevels_up, and locate_var_of_level_context::var_location.
Referenced by checkExprIsVarFree(), and transformSetOperationTree().
{
locate_var_of_level_context context;
context.var_location = -1; /* in case we find nothing */
context.sublevels_up = levelsup;
(void) query_or_expression_tree_walker(node,
locate_var_of_level_walker,
(void *) &context,
0);
return context.var_location;
}
| static bool locate_var_of_level_walker | ( | Node * | node, | |
| locate_var_of_level_context * | context | |||
| ) | [static] |
Definition at line 446 of file var.c.
References expression_tree_walker(), IsA, Var::location, NULL, query_tree_walker(), locate_var_of_level_context::sublevels_up, locate_var_of_level_context::var_location, and Var::varlevelsup.
Referenced by locate_var_of_level().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varlevelsup == context->sublevels_up &&
var->location >= 0)
{
context->var_location = var->location;
return true; /* abort tree traversal and return true */
}
return false;
}
if (IsA(node, CurrentOfExpr))
{
/* since CurrentOfExpr doesn't carry location, nothing we can do */
return false;
}
/* No extra code needed for PlaceHolderVar; just look in contained expr */
if (IsA(node, Query))
{
/* Recurse into subselects */
bool result;
context->sublevels_up++;
result = query_tree_walker((Query *) node,
locate_var_of_level_walker,
(void *) context,
0);
context->sublevels_up--;
return result;
}
return expression_tree_walker(node,
locate_var_of_level_walker,
(void *) context);
}
| List* pull_var_clause | ( | Node * | node, | |
| PVCAggregateBehavior | aggbehavior, | |||
| PVCPlaceHolderBehavior | phbehavior | |||
| ) |
Definition at line 516 of file var.c.
References pull_var_clause_context::aggbehavior, pull_var_clause_context::phbehavior, pull_var_clause_walker(), and pull_var_clause_context::varlist.
Referenced by AddRelationNewConstraints(), build_base_rel_tlists(), CreateTrigger(), distribute_qual_to_rels(), estimate_num_groups(), fix_placeholder_input_needed_levels(), flatten_tlist(), generate_base_implied_equalities_no_const(), make_subplanTargetList(), make_windowInputTargetList(), mark_placeholders_in_expr(), prepare_sort_from_pathkeys(), preprocess_targetlist(), qual_is_pushdown_safe(), and StoreRelCheck().
{
pull_var_clause_context context;
context.varlist = NIL;
context.aggbehavior = aggbehavior;
context.phbehavior = phbehavior;
pull_var_clause_walker(node, &context);
return context.varlist;
}
| static bool pull_var_clause_walker | ( | Node * | node, | |
| pull_var_clause_context * | context | |||
| ) | [static] |
Definition at line 530 of file var.c.
References pull_var_clause_context::aggbehavior, elog, ERROR, expression_tree_walker(), IsA, lappend(), NULL, pull_var_clause_context::phbehavior, PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_PLACEHOLDERS, PVC_REJECT_AGGREGATES, PVC_REJECT_PLACEHOLDERS, and pull_var_clause_context::varlist.
Referenced by pull_var_clause().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
if (((Var *) node)->varlevelsup != 0)
elog(ERROR, "Upper-level Var found where not expected");
context->varlist = lappend(context->varlist, node);
return false;
}
else if (IsA(node, Aggref))
{
if (((Aggref *) node)->agglevelsup != 0)
elog(ERROR, "Upper-level Aggref found where not expected");
switch (context->aggbehavior)
{
case PVC_REJECT_AGGREGATES:
elog(ERROR, "Aggref found where not expected");
break;
case PVC_INCLUDE_AGGREGATES:
context->varlist = lappend(context->varlist, node);
/* we do NOT descend into the contained expression */
return false;
case PVC_RECURSE_AGGREGATES:
/* ignore the aggregate, look at its argument instead */
break;
}
}
else if (IsA(node, PlaceHolderVar))
{
if (((PlaceHolderVar *) node)->phlevelsup != 0)
elog(ERROR, "Upper-level PlaceHolderVar found where not expected");
switch (context->phbehavior)
{
case PVC_REJECT_PLACEHOLDERS:
elog(ERROR, "PlaceHolderVar found where not expected");
break;
case PVC_INCLUDE_PLACEHOLDERS:
context->varlist = lappend(context->varlist, node);
/* we do NOT descend into the contained expression */
return false;
case PVC_RECURSE_PLACEHOLDERS:
/* ignore the placeholder, look at its argument instead */
break;
}
}
return expression_tree_walker(node, pull_var_clause_walker,
(void *) context);
}
Definition at line 212 of file var.c.
References pull_varattnos_walker(), pull_varattnos_context::varattnos, and pull_varattnos_context::varno.
Referenced by check_index_only(), check_selective_binary_conversion(), deparseReturningList(), postgresGetForeignRelSize(), and RelationGetIndexAttrBitmap().
{
pull_varattnos_context context;
context.varattnos = *varattnos;
context.varno = varno;
(void) pull_varattnos_walker(node, &context);
*varattnos = context.varattnos;
}
| static bool pull_varattnos_walker | ( | Node * | node, | |
| pull_varattnos_context * | context | |||
| ) | [static] |
Definition at line 225 of file var.c.
References Assert, bms_add_member(), expression_tree_walker(), FirstLowInvalidHeapAttributeNumber, IsA, NULL, Var::varattno, pull_varattnos_context::varattnos, Var::varlevelsup, pull_varattnos_context::varno, and Var::varno.
Referenced by pull_varattnos().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varno == context->varno && var->varlevelsup == 0)
context->varattnos =
bms_add_member(context->varattnos,
var->varattno - FirstLowInvalidHeapAttributeNumber);
return false;
}
/* Should not find an unplanned subquery */
Assert(!IsA(node, Query));
return expression_tree_walker(node, pull_varattnos_walker,
(void *) context);
}
Definition at line 96 of file var.c.
References pull_varnos_walker(), query_or_expression_tree_walker(), pull_varnos_context::sublevels_up, and pull_varnos_context::varnos.
Referenced by adjust_rowcompare_for_index(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), create_unique_path(), distribute_qual_to_rels(), examine_variable(), find_placeholder_info(), get_eclass_for_sort_expr(), join_is_removable(), make_outerjoininfo(), make_restrictinfo_internal(), match_clause_to_indexcol(), match_rowcompare_to_indexcol(), NumRelids(), and reduce_outer_joins_pass2().
{
pull_varnos_context context;
context.varnos = NULL;
context.sublevels_up = 0;
/*
* 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.
*/
query_or_expression_tree_walker(node,
pull_varnos_walker,
(void *) &context,
0);
return context.varnos;
}
Definition at line 121 of file var.c.
References pull_varnos_walker(), query_or_expression_tree_walker(), pull_varnos_context::sublevels_up, and pull_varnos_context::varnos.
Referenced by is_simple_subquery().
{
pull_varnos_context context;
context.varnos = NULL;
context.sublevels_up = levelsup;
/*
* 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.
*/
query_or_expression_tree_walker(node,
pull_varnos_walker,
(void *) &context,
0);
return context.varnos;
}
| static bool pull_varnos_walker | ( | Node * | node, | |
| pull_varnos_context * | context | |||
| ) | [static] |
Definition at line 141 of file var.c.
References bms_add_member(), bms_add_members(), bms_is_empty(), bms_join(), CurrentOfExpr::cvarno, expression_tree_walker(), IsA, NULL, PlaceHolderVar::phexpr, PlaceHolderVar::phlevelsup, PlaceHolderVar::phrels, query_tree_walker(), pull_varnos_context::sublevels_up, Var::varlevelsup, Var::varno, and pull_varnos_context::varnos.
Referenced by pull_varnos(), and pull_varnos_of_level().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varlevelsup == context->sublevels_up)
context->varnos = bms_add_member(context->varnos, var->varno);
return false;
}
if (IsA(node, CurrentOfExpr))
{
CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
if (context->sublevels_up == 0)
context->varnos = bms_add_member(context->varnos, cexpr->cvarno);
return false;
}
if (IsA(node, PlaceHolderVar))
{
/*
* Normally, we can just take the varnos in the contained expression.
* But if it is variable-free, use the PHV's syntactic relids.
*/
PlaceHolderVar *phv = (PlaceHolderVar *) node;
pull_varnos_context subcontext;
subcontext.varnos = NULL;
subcontext.sublevels_up = context->sublevels_up;
(void) pull_varnos_walker((Node *) phv->phexpr, &subcontext);
if (bms_is_empty(subcontext.varnos) &&
phv->phlevelsup == context->sublevels_up)
context->varnos = bms_add_members(context->varnos, phv->phrels);
else
context->varnos = bms_join(context->varnos, subcontext.varnos);
return false;
}
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
bool result;
context->sublevels_up++;
result = query_tree_walker((Query *) node, pull_varnos_walker,
(void *) context, 0);
context->sublevels_up--;
return result;
}
return expression_tree_walker(node, pull_varnos_walker,
(void *) context);
}
Definition at line 256 of file var.c.
References pull_vars_walker(), query_or_expression_tree_walker(), pull_vars_context::sublevels_up, and pull_vars_context::vars.
Referenced by extract_lateral_references().
{
pull_vars_context context;
context.vars = NIL;
context.sublevels_up = levelsup;
/*
* 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.
*/
query_or_expression_tree_walker(node,
pull_vars_walker,
(void *) &context,
0);
return context.vars;
}
| static bool pull_vars_walker | ( | Node * | node, | |
| pull_vars_context * | context | |||
| ) | [static] |
Definition at line 276 of file var.c.
References expression_tree_walker(), IsA, lappend(), NULL, PlaceHolderVar::phlevelsup, query_tree_walker(), pull_vars_context::sublevels_up, Var::varlevelsup, and pull_vars_context::vars.
Referenced by pull_vars_of_level().
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varlevelsup == context->sublevels_up)
context->vars = lappend(context->vars, var);
return false;
}
if (IsA(node, PlaceHolderVar))
{
PlaceHolderVar *phv = (PlaceHolderVar *) node;
if (phv->phlevelsup == context->sublevels_up)
context->vars = lappend(context->vars, phv);
/* we don't want to look into the contained expression */
return false;
}
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
bool result;
context->sublevels_up++;
result = query_tree_walker((Query *) node, pull_vars_walker,
(void *) context, 0);
context->sublevels_up--;
return result;
}
return expression_tree_walker(node, pull_vars_walker,
(void *) context);
}
1.7.1