#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); }