mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
8.4 pgindent run, with new combined Linux/FreeBSD/MinGW typedef list
provided by Andrew.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.5 2009/01/01 17:23:45 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.6 2009/06/11 14:49:00 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,7 +25,7 @@
|
||||
typedef enum
|
||||
{
|
||||
RECURSION_OK,
|
||||
RECURSION_NONRECURSIVETERM, /* inside the left-hand term */
|
||||
RECURSION_NONRECURSIVETERM, /* inside the left-hand term */
|
||||
RECURSION_SUBLINK, /* inside a sublink */
|
||||
RECURSION_OUTERJOIN, /* inside nullable side of an outer join */
|
||||
RECURSION_INTERSECT, /* underneath INTERSECT (ALL) */
|
||||
@ -33,7 +33,7 @@ typedef enum
|
||||
} RecursionContext;
|
||||
|
||||
/* Associated error messages --- each must have one %s for CTE name */
|
||||
static const char * const recursion_errormsgs[] = {
|
||||
static const char *const recursion_errormsgs[] = {
|
||||
/* RECURSION_OK */
|
||||
NULL,
|
||||
/* RECURSION_NONRECURSIVETERM */
|
||||
@ -56,10 +56,11 @@ static const char * const recursion_errormsgs[] = {
|
||||
*/
|
||||
typedef struct CteItem
|
||||
{
|
||||
CommonTableExpr *cte; /* One CTE to examine */
|
||||
int id; /* Its ID number for dependencies */
|
||||
Node *non_recursive_term; /* Its nonrecursive part, if identified */
|
||||
Bitmapset *depends_on; /* CTEs depended on (not including self) */
|
||||
CommonTableExpr *cte; /* One CTE to examine */
|
||||
int id; /* Its ID number for dependencies */
|
||||
Node *non_recursive_term; /* Its nonrecursive part, if
|
||||
* identified */
|
||||
Bitmapset *depends_on; /* CTEs depended on (not including self) */
|
||||
} CteItem;
|
||||
|
||||
/* CteState is what we need to pass around in the tree walkers */
|
||||
@ -67,7 +68,7 @@ typedef struct CteState
|
||||
{
|
||||
/* global state: */
|
||||
ParseState *pstate; /* global parse state */
|
||||
CteItem *items; /* array of CTEs and extra data */
|
||||
CteItem *items; /* array of CTEs and extra data */
|
||||
int numitems; /* number of CTEs */
|
||||
/* working state during a tree walk: */
|
||||
int curitem; /* index of item currently being examined */
|
||||
@ -94,8 +95,8 @@ static void checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate);
|
||||
|
||||
/*
|
||||
* transformWithClause -
|
||||
* Transform the list of WITH clause "common table expressions" into
|
||||
* Query nodes.
|
||||
* Transform the list of WITH clause "common table expressions" into
|
||||
* Query nodes.
|
||||
*
|
||||
* The result is the list of transformed CTEs to be put into the output
|
||||
* Query. (This is in fact the same as the ending value of p_ctenamespace,
|
||||
@ -111,11 +112,11 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
Assert(pstate->p_future_ctes == NIL);
|
||||
|
||||
/*
|
||||
* For either type of WITH, there must not be duplicate CTE names in
|
||||
* the list. Check this right away so we needn't worry later.
|
||||
* For either type of WITH, there must not be duplicate CTE names in the
|
||||
* list. Check this right away so we needn't worry later.
|
||||
*
|
||||
* Also, tentatively mark each CTE as non-recursive, and initialize
|
||||
* its reference count to zero.
|
||||
* Also, tentatively mark each CTE as non-recursive, and initialize its
|
||||
* reference count to zero.
|
||||
*/
|
||||
foreach(lc, withClause->ctes)
|
||||
{
|
||||
@ -129,8 +130,8 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
if (strcmp(cte->ctename, cte2->ctename) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_ALIAS),
|
||||
errmsg("WITH query name \"%s\" specified more than once",
|
||||
cte2->ctename),
|
||||
errmsg("WITH query name \"%s\" specified more than once",
|
||||
cte2->ctename),
|
||||
parser_errposition(pstate, cte2->location)));
|
||||
}
|
||||
|
||||
@ -141,12 +142,12 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
if (withClause->recursive)
|
||||
{
|
||||
/*
|
||||
* For WITH RECURSIVE, we rearrange the list elements if needed
|
||||
* to eliminate forward references. First, build a work array
|
||||
* and set up the data structure needed by the tree walkers.
|
||||
* For WITH RECURSIVE, we rearrange the list elements if needed to
|
||||
* eliminate forward references. First, build a work array and set up
|
||||
* the data structure needed by the tree walkers.
|
||||
*/
|
||||
CteState cstate;
|
||||
int i;
|
||||
CteState cstate;
|
||||
int i;
|
||||
|
||||
cstate.pstate = pstate;
|
||||
cstate.numitems = list_length(withClause->ctes);
|
||||
@ -171,10 +172,10 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
checkWellFormedRecursion(&cstate);
|
||||
|
||||
/*
|
||||
* Set up the ctenamespace for parse analysis. Per spec, all
|
||||
* the WITH items are visible to all others, so stuff them all in
|
||||
* before parse analysis. We build the list in safe processing
|
||||
* order so that the planner can process the queries in sequence.
|
||||
* Set up the ctenamespace for parse analysis. Per spec, all the WITH
|
||||
* items are visible to all others, so stuff them all in before parse
|
||||
* analysis. We build the list in safe processing order so that the
|
||||
* planner can process the queries in sequence.
|
||||
*/
|
||||
for (i = 0; i < cstate.numitems; i++)
|
||||
{
|
||||
@ -191,14 +192,14 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
CommonTableExpr *cte = cstate.items[i].cte;
|
||||
|
||||
/*
|
||||
* If it's recursive, we have to do a throwaway parse analysis
|
||||
* of the non-recursive term in order to determine the set of
|
||||
* output columns for the recursive CTE.
|
||||
* If it's recursive, we have to do a throwaway parse analysis of
|
||||
* the non-recursive term in order to determine the set of output
|
||||
* columns for the recursive CTE.
|
||||
*/
|
||||
if (cte->cterecursive)
|
||||
{
|
||||
Node *nrt;
|
||||
Query *nrq;
|
||||
Node *nrt;
|
||||
Query *nrq;
|
||||
|
||||
if (!cstate.items[i].non_recursive_term)
|
||||
elog(ERROR, "could not find non-recursive term for %s",
|
||||
@ -216,11 +217,10 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
{
|
||||
/*
|
||||
* For non-recursive WITH, just analyze each CTE in sequence and then
|
||||
* add it to the ctenamespace. This corresponds to the spec's
|
||||
* definition of the scope of each WITH name. However, to allow
|
||||
* error reports to be aware of the possibility of an erroneous
|
||||
* reference, we maintain a list in p_future_ctes of the
|
||||
* not-yet-visible CTEs.
|
||||
* add it to the ctenamespace. This corresponds to the spec's
|
||||
* definition of the scope of each WITH name. However, to allow error
|
||||
* reports to be aware of the possibility of an erroneous reference,
|
||||
* we maintain a list in p_future_ctes of the not-yet-visible CTEs.
|
||||
*/
|
||||
pstate->p_future_ctes = list_copy(withClause->ctes);
|
||||
|
||||
@ -232,7 +232,7 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
pstate->p_ctenamespace = lappend(pstate->p_ctenamespace, cte);
|
||||
pstate->p_future_ctes = list_delete_first(pstate->p_future_ctes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pstate->p_ctenamespace;
|
||||
}
|
||||
@ -246,7 +246,7 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
|
||||
static void
|
||||
analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
{
|
||||
Query *query;
|
||||
Query *query;
|
||||
|
||||
/* Analysis not done already */
|
||||
Assert(IsA(cte->ctequery, SelectStmt));
|
||||
@ -268,7 +268,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("subquery in WITH cannot have SELECT INTO"),
|
||||
parser_errposition(pstate,
|
||||
exprLocation((Node *) query->intoClause))));
|
||||
exprLocation((Node *) query->intoClause))));
|
||||
|
||||
if (!cte->cterecursive)
|
||||
{
|
||||
@ -279,9 +279,9 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
{
|
||||
/*
|
||||
* Verify that the previously determined output column types match
|
||||
* what the query really produced. We have to check this because
|
||||
* the recursive term could have overridden the non-recursive term,
|
||||
* and we don't have any easy way to fix that.
|
||||
* what the query really produced. We have to check this because the
|
||||
* recursive term could have overridden the non-recursive term, and we
|
||||
* don't have any easy way to fix that.
|
||||
*/
|
||||
ListCell *lctlist,
|
||||
*lctyp,
|
||||
@ -294,7 +294,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
foreach(lctlist, query->targetList)
|
||||
{
|
||||
TargetEntry *te = (TargetEntry *) lfirst(lctlist);
|
||||
Node *texpr;
|
||||
Node *texpr;
|
||||
|
||||
if (te->resjunk)
|
||||
continue;
|
||||
@ -310,7 +310,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
errmsg("recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall",
|
||||
cte->ctename, varattno,
|
||||
format_type_with_typemod(lfirst_oid(lctyp),
|
||||
lfirst_int(lctypmod)),
|
||||
lfirst_int(lctypmod)),
|
||||
format_type_with_typemod(exprType(texpr),
|
||||
exprTypmod(texpr))),
|
||||
errhint("Cast the output of the non-recursive term to the correct type."),
|
||||
@ -318,7 +318,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
|
||||
lctyp = lnext(lctyp);
|
||||
lctypmod = lnext(lctypmod);
|
||||
}
|
||||
if (lctyp != NULL || lctypmod != NULL) /* shouldn't happen */
|
||||
if (lctyp != NULL || lctypmod != NULL) /* shouldn't happen */
|
||||
elog(ERROR, "wrong number of output columns in WITH");
|
||||
}
|
||||
}
|
||||
@ -335,10 +335,10 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
|
||||
|
||||
/*
|
||||
* We need to determine column names and types. The alias column names
|
||||
* override anything coming from the query itself. (Note: the SQL spec
|
||||
* says that the alias list must be empty or exactly as long as the
|
||||
* output column set; but we allow it to be shorter for consistency
|
||||
* with Alias handling.)
|
||||
* override anything coming from the query itself. (Note: the SQL spec
|
||||
* says that the alias list must be empty or exactly as long as the output
|
||||
* column set; but we allow it to be shorter for consistency with Alias
|
||||
* handling.)
|
||||
*/
|
||||
cte->ctecolnames = copyObject(cte->aliascolnames);
|
||||
cte->ctecoltypes = cte->ctecoltypmods = NIL;
|
||||
@ -363,13 +363,14 @@ analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
|
||||
}
|
||||
coltype = exprType((Node *) te->expr);
|
||||
coltypmod = exprTypmod((Node *) te->expr);
|
||||
|
||||
/*
|
||||
* If the CTE is recursive, force the exposed column type of any
|
||||
* "unknown" column to "text". This corresponds to the fact that
|
||||
* SELECT 'foo' UNION SELECT 'bar' will ultimately produce text.
|
||||
* We might see "unknown" as a result of an untyped literal in
|
||||
* the non-recursive term's select list, and if we don't convert
|
||||
* to text then we'll have a mismatch against the UNION result.
|
||||
* "unknown" column to "text". This corresponds to the fact that
|
||||
* SELECT 'foo' UNION SELECT 'bar' will ultimately produce text. We
|
||||
* might see "unknown" as a result of an untyped literal in the
|
||||
* non-recursive term's select list, and if we don't convert to text
|
||||
* then we'll have a mismatch against the UNION result.
|
||||
*/
|
||||
if (cte->cterecursive && coltype == UNKNOWNOID)
|
||||
{
|
||||
@ -426,21 +427,21 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
/* If unqualified name, might be a CTE reference */
|
||||
if (!rv->schemaname)
|
||||
{
|
||||
ListCell *lc;
|
||||
int i;
|
||||
ListCell *lc;
|
||||
int i;
|
||||
|
||||
/* ... but first see if it's captured by an inner WITH */
|
||||
foreach(lc, cstate->innerwiths)
|
||||
{
|
||||
List *withlist = (List *) lfirst(lc);
|
||||
ListCell *lc2;
|
||||
List *withlist = (List *) lfirst(lc);
|
||||
ListCell *lc2;
|
||||
|
||||
foreach(lc2, withlist)
|
||||
{
|
||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
|
||||
|
||||
if (strcmp(rv->relname, cte->ctename) == 0)
|
||||
return false; /* yes, so bail out */
|
||||
return false; /* yes, so bail out */
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +452,7 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
|
||||
if (strcmp(rv->relname, cte->ctename) == 0)
|
||||
{
|
||||
int myindex = cstate->curitem;
|
||||
int myindex = cstate->curitem;
|
||||
|
||||
if (i != myindex)
|
||||
{
|
||||
@ -474,7 +475,7 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
if (IsA(node, SelectStmt))
|
||||
{
|
||||
SelectStmt *stmt = (SelectStmt *) node;
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
if (stmt->withClause)
|
||||
{
|
||||
@ -482,8 +483,8 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
{
|
||||
/*
|
||||
* In the RECURSIVE case, all query names of the WITH are
|
||||
* visible to all WITH items as well as the main query.
|
||||
* So push them all on, process, pop them all off.
|
||||
* visible to all WITH items as well as the main query. So
|
||||
* push them all on, process, pop them all off.
|
||||
*/
|
||||
cstate->innerwiths = lcons(stmt->withClause->ctes,
|
||||
cstate->innerwiths);
|
||||
@ -501,8 +502,8 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In the non-RECURSIVE case, query names are visible to
|
||||
* the WITH items after them and to the main query.
|
||||
* In the non-RECURSIVE case, query names are visible to the
|
||||
* WITH items after them and to the main query.
|
||||
*/
|
||||
ListCell *cell1;
|
||||
|
||||
@ -528,9 +529,9 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
if (IsA(node, WithClause))
|
||||
{
|
||||
/*
|
||||
* Prevent raw_expression_tree_walker from recursing directly into
|
||||
* a WITH clause. We need that to happen only under the control
|
||||
* of the code above.
|
||||
* Prevent raw_expression_tree_walker from recursing directly into a
|
||||
* WITH clause. We need that to happen only under the control of the
|
||||
* code above.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
@ -545,7 +546,8 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
static void
|
||||
TopologicalSort(ParseState *pstate, CteItem *items, int numitems)
|
||||
{
|
||||
int i, j;
|
||||
int i,
|
||||
j;
|
||||
|
||||
/* for each position in sequence ... */
|
||||
for (i = 0; i < numitems; i++)
|
||||
@ -561,24 +563,25 @@ TopologicalSort(ParseState *pstate, CteItem *items, int numitems)
|
||||
if (j >= numitems)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("mutual recursion between WITH items is not implemented"),
|
||||
errmsg("mutual recursion between WITH items is not implemented"),
|
||||
parser_errposition(pstate, items[i].cte->location)));
|
||||
|
||||
/*
|
||||
* Found one. Move it to front and remove it from every other
|
||||
* item's dependencies.
|
||||
* Found one. Move it to front and remove it from every other item's
|
||||
* dependencies.
|
||||
*/
|
||||
if (i != j)
|
||||
{
|
||||
CteItem tmp;
|
||||
|
||||
CteItem tmp;
|
||||
|
||||
tmp = items[i];
|
||||
items[i] = items[j];
|
||||
items[j] = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Items up through i are known to have no dependencies left,
|
||||
* so we can skip them in this loop.
|
||||
* Items up through i are known to have no dependencies left, so we
|
||||
* can skip them in this loop.
|
||||
*/
|
||||
for (j = i + 1; j < numitems; j++)
|
||||
{
|
||||
@ -600,9 +603,9 @@ checkWellFormedRecursion(CteState *cstate)
|
||||
for (i = 0; i < cstate->numitems; i++)
|
||||
{
|
||||
CommonTableExpr *cte = cstate->items[i].cte;
|
||||
SelectStmt *stmt = (SelectStmt *) cte->ctequery;
|
||||
SelectStmt *stmt = (SelectStmt *) cte->ctequery;
|
||||
|
||||
Assert(IsA(stmt, SelectStmt)); /* not analyzed yet */
|
||||
Assert(IsA(stmt, SelectStmt)); /* not analyzed yet */
|
||||
|
||||
/* Ignore items that weren't found to be recursive */
|
||||
if (!cte->cterecursive)
|
||||
@ -631,22 +634,22 @@ checkWellFormedRecursion(CteState *cstate)
|
||||
cstate->context = RECURSION_OK;
|
||||
checkWellFormedRecursionWalker((Node *) stmt->rarg, cstate);
|
||||
Assert(cstate->innerwiths == NIL);
|
||||
if (cstate->selfrefcount != 1) /* shouldn't happen */
|
||||
if (cstate->selfrefcount != 1) /* shouldn't happen */
|
||||
elog(ERROR, "missing recursive reference");
|
||||
|
||||
/*
|
||||
* Disallow ORDER BY and similar decoration atop the UNION.
|
||||
* These don't make sense because it's impossible to figure out what
|
||||
* they mean when we have only part of the recursive query's results.
|
||||
* (If we did allow them, we'd have to check for recursive references
|
||||
* Disallow ORDER BY and similar decoration atop the UNION. These
|
||||
* don't make sense because it's impossible to figure out what they
|
||||
* mean when we have only part of the recursive query's results. (If
|
||||
* we did allow them, we'd have to check for recursive references
|
||||
* inside these subtrees.)
|
||||
*/
|
||||
if (stmt->sortClause)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("ORDER BY in a recursive query is not implemented"),
|
||||
errmsg("ORDER BY in a recursive query is not implemented"),
|
||||
parser_errposition(cstate->pstate,
|
||||
exprLocation((Node *) stmt->sortClause))));
|
||||
exprLocation((Node *) stmt->sortClause))));
|
||||
if (stmt->limitOffset)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
@ -664,7 +667,7 @@ checkWellFormedRecursion(CteState *cstate)
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("FOR UPDATE/SHARE in a recursive query is not implemented"),
|
||||
parser_errposition(cstate->pstate,
|
||||
exprLocation((Node *) stmt->lockingClause))));
|
||||
exprLocation((Node *) stmt->lockingClause))));
|
||||
|
||||
/*
|
||||
* Save non_recursive_term.
|
||||
@ -690,21 +693,21 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
/* If unqualified name, might be a CTE reference */
|
||||
if (!rv->schemaname)
|
||||
{
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
CommonTableExpr *mycte;
|
||||
|
||||
/* ... but first see if it's captured by an inner WITH */
|
||||
foreach(lc, cstate->innerwiths)
|
||||
{
|
||||
List *withlist = (List *) lfirst(lc);
|
||||
ListCell *lc2;
|
||||
List *withlist = (List *) lfirst(lc);
|
||||
ListCell *lc2;
|
||||
|
||||
foreach(lc2, withlist)
|
||||
{
|
||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc2);
|
||||
|
||||
if (strcmp(rv->relname, cte->ctename) == 0)
|
||||
return false; /* yes, so bail out */
|
||||
return false; /* yes, so bail out */
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,7 +738,7 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
if (IsA(node, SelectStmt))
|
||||
{
|
||||
SelectStmt *stmt = (SelectStmt *) node;
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
if (stmt->withClause)
|
||||
{
|
||||
@ -743,8 +746,8 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
{
|
||||
/*
|
||||
* In the RECURSIVE case, all query names of the WITH are
|
||||
* visible to all WITH items as well as the main query.
|
||||
* So push them all on, process, pop them all off.
|
||||
* visible to all WITH items as well as the main query. So
|
||||
* push them all on, process, pop them all off.
|
||||
*/
|
||||
cstate->innerwiths = lcons(stmt->withClause->ctes,
|
||||
cstate->innerwiths);
|
||||
@ -760,8 +763,8 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In the non-RECURSIVE case, query names are visible to
|
||||
* the WITH items after them and to the main query.
|
||||
* In the non-RECURSIVE case, query names are visible to the
|
||||
* WITH items after them and to the main query.
|
||||
*/
|
||||
ListCell *cell1;
|
||||
|
||||
@ -779,22 +782,22 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
}
|
||||
}
|
||||
else
|
||||
checkWellFormedSelectStmt(stmt, cstate);
|
||||
checkWellFormedSelectStmt(stmt, cstate);
|
||||
/* We're done examining the SelectStmt */
|
||||
return false;
|
||||
}
|
||||
if (IsA(node, WithClause))
|
||||
{
|
||||
/*
|
||||
* Prevent raw_expression_tree_walker from recursing directly into
|
||||
* a WITH clause. We need that to happen only under the control
|
||||
* of the code above.
|
||||
* Prevent raw_expression_tree_walker from recursing directly into a
|
||||
* WITH clause. We need that to happen only under the control of the
|
||||
* code above.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
if (IsA(node, JoinExpr))
|
||||
{
|
||||
JoinExpr *j = (JoinExpr *) node;
|
||||
JoinExpr *j = (JoinExpr *) node;
|
||||
|
||||
switch (j->jointype)
|
||||
{
|
||||
@ -835,7 +838,7 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
}
|
||||
if (IsA(node, SubLink))
|
||||
{
|
||||
SubLink *sl = (SubLink *) node;
|
||||
SubLink *sl = (SubLink *) node;
|
||||
|
||||
/*
|
||||
* we intentionally override outer context, since subquery is
|
||||
|
Reference in New Issue
Block a user