1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

First cut at full support for OUTER JOINs. There are still a few loose

ends to clean up (see my message of same date to pghackers), but mostly
it works.  INITDB REQUIRED!
This commit is contained in:
Tom Lane
2000-09-12 21:07:18 +00:00
parent b5c0ab278b
commit ed5003c584
93 changed files with 6386 additions and 4262 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.26 2000/04/12 17:15:24 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.27 2000/09/12 21:06:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,17 +16,25 @@
#include "postgres.h"
#include "nodes/plannodes.h"
#include "optimizer/clauses.h"
#include "optimizer/var.h"
typedef struct
{
List *varlist;
int sublevels_up;
} pull_varnos_context;
typedef struct
{
List *varlist;
bool includeUpperVars;
} pull_var_clause_context;
static bool pull_varnos_walker(Node *node, List **listptr);
static bool pull_varnos_walker(Node *node,
pull_varnos_context *context);
static bool contain_var_clause_walker(Node *node, void *context);
static bool pull_var_clause_walker(Node *node,
pull_var_clause_context *context);
@@ -35,21 +43,39 @@ static bool pull_var_clause_walker(Node *node,
/*
* pull_varnos
*
* Create a list of all the distinct varnos present in a parsetree
* (tlist or qual). Note that only varnos attached to level-zero
* Vars are considered --- upper Vars refer to some other rtable!
* Create a list of all the distinct varnos present in a parsetree.
* Only varnos that reference level-zero rtable entries are considered.
*
* NOTE: unlike other routines in this file, pull_varnos() is used on
* not-yet-planned expressions. It may therefore find bare SubLinks,
* and if so it needs to recurse into them to look for uplevel references
* to the desired rtable level! But when we find a completed SubPlan,
* we only need to look at the parameters passed to the subplan.
*/
List *
pull_varnos(Node *node)
{
List *result = NIL;
pull_varnos_context context;
pull_varnos_walker(node, &result);
return result;
context.varlist = NIL;
context.sublevels_up = 0;
/*
* Must be prepared to start with a Query or a bare expression tree;
* if it's a Query, go straight to query_tree_walker to make sure that
* sublevels_up doesn't get incremented prematurely.
*/
if (node && IsA(node, Query))
query_tree_walker((Query *) node, pull_varnos_walker,
(void *) &context);
else
pull_varnos_walker(node, &context);
return context.varlist;
}
static bool
pull_varnos_walker(Node *node, List **listptr)
pull_varnos_walker(Node *node, pull_varnos_context *context)
{
if (node == NULL)
return false;
@@ -57,11 +83,42 @@ pull_varnos_walker(Node *node, List **listptr)
{
Var *var = (Var *) node;
if (var->varlevelsup == 0 && !intMember(var->varno, *listptr))
*listptr = lconsi(var->varno, *listptr);
if (var->varlevelsup == context->sublevels_up &&
!intMember(var->varno, context->varlist))
context->varlist = lconsi(var->varno, context->varlist);
return false;
}
return expression_tree_walker(node, pull_varnos_walker, (void *) listptr);
if (is_subplan(node))
{
/*
* Already-planned subquery. Examine the args list (parameters
* to be passed to subquery), as well as the "oper" list which
* is executed by the outer query. But short-circuit recursion into
* the subquery itself, which would be a waste of effort.
*/
Expr *expr = (Expr *) node;
if (pull_varnos_walker((Node*) ((SubPlan*) expr->oper)->sublink->oper,
context))
return true;
if (pull_varnos_walker((Node *) expr->args,
context))
return true;
return false;
}
if (IsA(node, Query))
{
/* Recurse into not-yet-planned subquery */
bool result;
context->sublevels_up++;
result = query_tree_walker((Query *) node, pull_varnos_walker,
(void *) context);
context->sublevels_up--;
return result;
}
return expression_tree_walker(node, pull_varnos_walker,
(void *) context);
}
/*