/*------------------------------------------------------------------------- * * var_utils.c * Utilities regarding vars * * Copyright (c) Citus Data, Inc. *------------------------------------------------------------------------- */ #include "distributed/pg_version_constants.h" #include "postgres.h" #include "distributed/var_utils.h" #include "parser/parsetree.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "nodes/nodes.h" #include "nodes/nodeFuncs.h" #include "nodes/pg_list.h" #include "utils/builtins.h" #include "utils/guc.h" #include "utils/lsyscache.h" #include "nodes/primnodes.h" #if PG_VERSION_NUM >= PG_VERSION_12 #include "nodes/pathnodes.h" #else #include "nodes/relation.h" #endif typedef struct PullTableContext { List *referencedRteList; /* stores all the RTEs that are referenced by a var */ List *rtableList; /* contains rtable's of upper queries, including the current query */ }PullTableContext; static bool PullAllRangeTablesEntriesWalker(Node *node, PullTableContext *pullTableContext); /* * PullAllRangeTablesEntries collects all the range table entries that are referenced * in the given query. The range table entry could be outside of the given query but a var * could exist that points to it. * rtableList should contain list of rtables up to this query from the top query. */ List * PullAllRangeTablesEntries(Query *query, List *rtableList) { PullTableContext p; p.rtableList = rtableList; p.referencedRteList = NIL; query_or_expression_tree_walker((Node *) query, PullAllRangeTablesEntriesWalker, (void *) &p, 0); return p.referencedRteList; } /* * PullAllRangeTablesEntriesWalker descends into the given node and collects * all range table entries that are referenced by a Var. */ static bool PullAllRangeTablesEntriesWalker(Node *node, PullTableContext *pullTableContext) { if (node == NULL) { return false; } else if (IsA(node, Var)) { Var *var = (Var *) node; List *rtableList = pullTableContext->rtableList; int index = var->varlevelsup; if (index >= list_length(rtableList) || index < 0) { ereport(ERROR, (errmsg("unexpected state: %d is not between 0-%d", index, list_length(rtableList)))); } List *rtable = (List *) list_nth(rtableList, index); RangeTblEntry *rte = (RangeTblEntry *) list_nth(rtable, var->varno - 1); pullTableContext->referencedRteList = lappend(pullTableContext->referencedRteList, rte); return false; } else if (IsA(node, PlaceHolderVar)) { /* PlaceHolderVar *phv = (PlaceHolderVar *) node; */ /* we don't want to look into the contained expression */ return false; } else if (IsA(node, Query)) { /* Recurse into RTE subquery or not-yet-planned sublink subquery */ Query *query = (Query *) node; pullTableContext->rtableList = lcons(query->rtable, pullTableContext->rtableList); bool result = query_tree_walker(query, PullAllRangeTablesEntriesWalker, (void *) pullTableContext, 0); pullTableContext->rtableList = list_delete_first(pullTableContext->rtableList); return result; } else { return expression_tree_walker(node, PullAllRangeTablesEntriesWalker, (void *) pullTableContext); } }